diff --git a/build.md b/build.md
new file mode 100644
index 0000000..8a333c1
--- /dev/null
+++ b/build.md
@@ -0,0 +1,37 @@
+
+# TPQuery Building
+
+## Requirements
+
+* java sdk 1.8 or higher.
+* maven 3 or higher.
+
+## Create build artifacts
+
+cd project-root/;
+mvn -Ptpquery-build clean package;
+
+## Change pom.xml versions
+
+cd project-root/;
+mvn versions:set -DnewVersion=2.3.4-SNAPSHOT
+
+## Make release build
+
+cd project-root/;
+mvn -Ptpquery-build clean package;
+mvn -B -Dusername=(scm_username) clean install release:clean release:prepare release:perform;
+
+## Make site
+
+cd project-root/;
+mvn -Ptpquery-build-site clean install site:site
+Optional add -DstagingDirectory=/tmp/tpquery-build-fullsite
+And then manual upload.
+
+## Check for dependency-updates
+
+cd project-root/;
+mvn versions:display-plugin-updates|grep ">"|uniq;
+mvn versions:display-dependency-updates|grep ">"|uniq;
+
diff --git a/license.txt b/license.txt
new file mode 100644
index 0000000..d6111a8
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,21 @@
+Copyright (c) 2015, Willem Cazander
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5d7e863
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,478 @@
+
+ 4.0.0
+ net.forwardfire.tpquery
+ tpquery
+ 0.0.1-SNAPSHOT
+ pom
+ tpquery
+ TemplatedPreparedQuery
+ 2007
+
+ ForwardFire.net
+ http://www.forwardfire.net/
+
+
+
+ BSD License
+ license.txt
+ repo
+ BSD 2-Clause License
+
+
+
+ 3.0.1
+
+
+ tpquery-executor-jdbc
+ tpquery-executor-jpa
+ tpquery-store
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.12
+
+
+ org.apache.commons
+ commons-lang3
+ 3.4
+
+
+ junit
+ junit
+ 4.12
+
+
+ ch.qos.logback
+ logback-classic
+ 1.1.3
+
+
+ com.h2database
+ h2
+ 1.4.187
+
+
+ postgresql
+ postgresql
+ 9.1-901-1.jdbc4
+
+
+ org.hibernate
+ hibernate-entitymanager
+ 5.0.0.Beta2
+
+
+ org.hibernate
+ hibernate-validator
+ 5.2.0.CR1
+
+
+ org.apache.tomcat
+ tomcat-jasper-el
+ 8.0.23
+
+
+ javax
+ javaee-api
+ 7.0
+
+
+ org.codehaus.sonar-plugins.java
+ sonar-jacoco-listeners
+ 3.2
+
+
+
+
+
+ junit
+ junit
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+ com.h2database
+ h2
+ test
+
+
+ postgresql
+ postgresql
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.8
+
+
+ maven-compiler-plugin
+ 3.0
+
+ ${project.build.sourceEncoding}
+
+ ${project.build.sourceVersion}
+
+
+
+ maven-source-plugin
+ 2.2.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+ 3.4
+
+
+ org.apache.maven.doxia
+ doxia-module-markdown
+ 1.6
+
+
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+ 2.8
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.4
+
+
+ org.codehaus.mojo
+ findbugs-maven-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 2.15
+
+
+ org.codehaus.mojo
+ taglist-maven-plugin
+ 2.4
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.18.1
+
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+ 2.18.1
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.7.4.201502262128
+
+
+
+
+
+
+
+ tpquery-test-none
+
+ true
+
+
+
+ tpquery-test-jacoco
+
+
+
+ maven-surefire-plugin
+
+
+
+ listener
+ org.sonar.java.jacoco.JUnitListener
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ jacoco-prepare-agent
+ initialize
+ true
+
+ prepare-agent
+
+
+
+
+
+
+
+
+ org.codehaus.sonar-plugins.java
+ sonar-jacoco-listeners
+ test
+
+
+
+
+ tpquery-test-jacoco-merge
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+ true
+ ../target/jacoco.exec
+
+
+ ${project.build.directory}
+
+ *.exec
+
+
+
+
+
+
+
+
+
+ tpquery-build
+
+
+
+ maven-source-plugin
+
+
+
+
+
+ tpquery-build-site
+
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+
+
+ org.apache.maven.shared
+ maven-shared-jar
+ 1.1
+
+
+ org.apache.bcel
+ bcel
+
+
+
+
+ com.google.code.findbugs
+ bcel-findbugs
+ 6.0
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ copy-project-markdown
+ generate-sources
+ false
+
+ run
+
+
+
+ Copy project markdown to site.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+
+ true
+ false
+ false
+
+
+
+
+
+ dependencies
+ dependency-convergence
+ dependency-info
+ dependency-management
+
+
+
+ issue-tracking
+ license
+
+
+ plugin-management
+ plugins
+
+ scm
+ summary
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+ true
+ true
+ true
+ 512m
+ true
+ true
+
+
+
+
+ aggregate
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+
+ true
+ true
+ ${project.build.sourceEncoding}
+ 100
+ ${project.build.javaVersion}
+
+
+
+ org.codehaus.mojo
+ findbugs-maven-plugin
+
+ true
+ true
+ true
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+ true
+ true
+ src/config/checkstyle.xml
+
+
+
+ org.codehaus.mojo
+ taglist-maven-plugin
+
+ true
+
+ @todo
+ @deprecated
+ HELP
+ TODO
+ FIXME
+ LATER
+ ERROR
+ SOMETHING
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+
+ true
+
+
+
+
+ report-only
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+ true
+ report
+
+
+
+
+
+
+ tpquery-sonar
+
+ jdbc:postgres://localhost/ff-sonar
+ ff-sonar
+ sonar-ff
+ http://localhost:9000
+ target/surefire-reports
+ target/jacoco.exec
+
+
+
+
diff --git a/src/config/checkstyle.xml b/src/config/checkstyle.xml
new file mode 100644
index 0000000..3c30a5e
--- /dev/null
+++ b/src/config/checkstyle.xml
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/site/markdown/download.md b/src/site/markdown/download.md
new file mode 100644
index 0000000..48722a6
--- /dev/null
+++ b/src/site/markdown/download.md
@@ -0,0 +1,32 @@
+
+
+# TPQuery Download
+
+
+## Download location
+
+Grep the latest release from: [link](http://todo.org/releases/tpquery/)
+
+
+
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
new file mode 100644
index 0000000..c35e8ae
--- /dev/null
+++ b/src/site/markdown/index.md
@@ -0,0 +1,38 @@
+
+
+# TPQuery Home
+
+TPQuery is templated prepared statement store.
+
+## Features
+
+* Named parameters
+* Include query parts
+* Default values
+* Extra parameter types like LIST and RAW
+* QuerySets are nestable.
+* Prepared statement cache if possibe.
+* Multiple languages supported.
+* Validation
+
diff --git a/src/site/resources/css/site.css b/src/site/resources/css/site.css
new file mode 100644
index 0000000..1ce0f07
--- /dev/null
+++ b/src/site/resources/css/site.css
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.breadcrumb,#bannerLeft,#bannerRight,#poweredBy {
+ display: none
+}
+
diff --git a/src/site/resources/img/logo/tpquery-topbar.png b/src/site/resources/img/logo/tpquery-topbar.png
new file mode 100644
index 0000000..7663e44
Binary files /dev/null and b/src/site/resources/img/logo/tpquery-topbar.png differ
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..d6e4172
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,51 @@
+
+
+
+
+ org.apache.maven.skins
+ maven-fluido-skin
+ 1.3.1
+
+
+
+ true
+ width: 90%;
+
+ TPQuery
+ ${project.name}
+ /img/logo/tpquery-topbar.png
+ /index.html
+
+ false
+
+ false
+ false
+
+
+
+
+
+
+
diff --git a/todo.md b/todo.md
new file mode 100644
index 0000000..db0ce54
--- /dev/null
+++ b/todo.md
@@ -0,0 +1,19 @@
+# TPQuery todo
+
+## Current ERRATA
+
+* None ?
+
+## Todo list
+
+* finish jdoc
+* finish site
+* rename prepared writers
+* Add jmx stats bean
+
+## Ideas
+
+* Create eclipse plugin
+* add mm auto column.
+* add hibernate config plugin
+
diff --git a/tpquery-executor-jdbc/pom.xml b/tpquery-executor-jdbc/pom.xml
new file mode 100644
index 0000000..412e739
--- /dev/null
+++ b/tpquery-executor-jdbc/pom.xml
@@ -0,0 +1,19 @@
+
+ 4.0.0
+
+ net.forwardfire.tpquery
+ tpquery
+ 0.0.1-SNAPSHOT
+
+ tpquery-executor-jdbc
+ tpquery-executor-jdbc
+
+
+ ${project.groupId}
+ tpquery-store
+ ${project.version}
+ compile
+
+
+
\ No newline at end of file
diff --git a/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/SQLExceptionRuntime.java b/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/SQLExceptionRuntime.java
new file mode 100644
index 0000000..9addb8b
--- /dev/null
+++ b/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/SQLExceptionRuntime.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.store.executor.jdbc;
+
+import java.sql.SQLException;
+
+@SuppressWarnings("serial")
+public class SQLExceptionRuntime extends RuntimeException {
+
+ public SQLExceptionRuntime(SQLException parent) {
+ super(parent);
+ }
+
+ public static SQLExceptionRuntime wrap(SQLException e) {
+ return new SQLExceptionRuntime(e);
+ }
+
+ public static SQLExceptionRuntime wrapAndClose(AutoCloseable closeable,SQLException e) {
+ return close(closeable,wrap(e));
+ }
+
+ protected static SQLExceptionRuntime close(AutoCloseable closeable,SQLExceptionRuntime parent) {
+ try {
+ closeable.close();
+ } catch (Exception ee) {
+ parent.addSuppressed(ee);
+ }
+ return parent;
+ }
+}
diff --git a/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/TPQExecutorJdbc.java b/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/TPQExecutorJdbc.java
new file mode 100644
index 0000000..7a58c37
--- /dev/null
+++ b/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/TPQExecutorJdbc.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.store.executor.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Objects;
+
+import net.forwardfire.tpquery.TPQFactory;
+import net.forwardfire.tpquery.store.executor.AbstractTPQExecutor;
+import net.forwardfire.tpquery.store.executor.TPQExecutorContext;
+
+public class TPQExecutorJdbc extends AbstractTPQExecutor {
+
+ public TPQExecutorJdbc(TPQExecutorContext context) {
+ super(context);
+ registrateStatementCreator(TPQFactory.StatementLanguage.SQL, (connection,statementText) -> {
+ try {
+ return connection.prepareStatement(statementText);
+ } catch (SQLException e) {
+ throw SQLExceptionRuntime.wrap(e);
+ }
+ });
+ }
+
+ public PreparedStatement execute(Connection connection,String queryName) {
+ return execute(connection, queryName, null);
+ }
+
+ public PreparedStatement execute(Connection connection,String queryName,Map parameters) {
+ return execute(createPreparedStatement(connection, queryName, parameters));
+ }
+
+ protected PreparedStatement execute(PreparedStatement statement) {
+ Objects.requireNonNull(statement,"Can't execute with null statement.");
+ try {
+ statement.execute();
+ return statement;
+ } catch (SQLException e) {
+ throw SQLExceptionRuntime.wrapAndClose(statement, e);
+ }
+ }
+
+ @Override
+ protected int executeUpdate(PreparedStatement statement) {
+ Objects.requireNonNull(statement,"Can't execute update with null statement.");
+ try {
+ int result = statement.executeUpdate();
+ statement.close();
+ return result;
+ } catch (SQLException e) {
+ throw SQLExceptionRuntime.wrapAndClose(statement, e);
+ }
+ }
+
+ @Override
+ protected void prepareParameterValue(PreparedStatement statement,int index, Object value) {
+ try {
+ statement.setObject(index,value);
+ } catch (SQLException e) {
+ throw SQLExceptionRuntime.wrap(e);
+ }
+ }
+
+ @Override
+ protected void prepareTimeout(PreparedStatement statement, Integer timeout) {
+ try {
+ statement.setQueryTimeout(timeout);
+ } catch (SQLException e) {
+ throw SQLExceptionRuntime.wrap(e);
+ }
+ }
+}
diff --git a/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/package-info.java b/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/package-info.java
new file mode 100644
index 0000000..8e5aec7
--- /dev/null
+++ b/tpquery-executor-jdbc/src/main/java/net/forwardfire/tpquery/store/executor/jdbc/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Jdbc executor.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.store.executor.jdbc;
diff --git a/tpquery-executor-jdbc/src/test/java/net/forwardfire/tpquery/store/executor/jdbc/TPQExecutorJdbcTest.java b/tpquery-executor-jdbc/src/test/java/net/forwardfire/tpquery/store/executor/jdbc/TPQExecutorJdbcTest.java
new file mode 100644
index 0000000..8885f22
--- /dev/null
+++ b/tpquery-executor-jdbc/src/test/java/net/forwardfire/tpquery/store/executor/jdbc/TPQExecutorJdbcTest.java
@@ -0,0 +1,240 @@
+package net.forwardfire.tpquery.store.executor.jdbc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.forwardfire.tpquery.TPQManager;
+import net.forwardfire.tpquery.TPQFactory;
+import net.forwardfire.tpquery.store.executor.jdbc.SQLExceptionRuntime;
+import net.forwardfire.tpquery.store.executor.jdbc.TPQExecutorJdbc;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+
+public class TPQExecutorJdbcTest {
+
+ @BeforeClass
+ public static void setupLogging() {
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+ lc.reset(); // disable logging
+ }
+
+ @Test()
+ public void testAutoClose() throws Exception {
+ SQLExceptionRuntime e = new SQLExceptionRuntime(new SQLException("junit"));
+ SQLExceptionRuntime.close(new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ throw new IllegalArgumentException("test");
+ }
+ }, e);
+ assertTrue(e.getSuppressed().length>0);
+ }
+
+ @Test()
+ public void testExecuteUpdateNull() throws Exception {
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+ TPQManager store = TPQFactory
+ .createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem")
+ .setLanguage(TPQFactory.StatementLanguage.SQL)
+ .createQuery("createTable").appendText("CREATE TABLE test_table (id serial,data int)").build()
+ .createQuery("insertData").appendText("INSERT INTO test_table (data) VALUES (0)").build()
+ .createQuery("queryFail")
+ .parseStatement("update test_table tt set tt.data=$$data$$")
+ .createQueryParameter("data", Integer.class.getName())
+ .setNullable(true)
+ .build()
+ .build()
+ .createQuery("selectData").appendText("SELECT * FROM test_table").build()
+ .createQuery("selectDataNull")
+ .parseStatement("SELECT * FROM test_table tt WHERE (tt.data=$$data$$ OR ($$data$$ IS NULL AND tt.data IS NULL))")
+ .createQueryParameter("data", Integer.class.getName())
+ .setNullable(true)
+ .build()
+ .build()
+ .build()
+ .build();
+
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(store.getQueryExecutorContext());
+ exe.executeUpdate(connection, "junit.createTable");
+ exe.executeUpdate(connection, "junit.insertData");
+
+ printData(exe.execute(connection, "junit.selectData"));
+
+ exe.executeUpdate(connection, "junit.queryFail");
+
+ printData(exe.execute(connection, "junit.selectData"));
+
+ Map testData = new HashMap<>();
+ testData.put("data",null);
+
+ printData(exe.execute(connection, "junit.selectDataNull",testData));
+ }
+ }
+
+ @Test(expected=SQLExceptionRuntime.class)
+ public void testExecuteUpdateFail() throws Exception {
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+ TPQManager store = TPQFactory
+ .createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem")
+ .setLanguage(TPQFactory.StatementLanguage.SQL)
+ .createQuery("createTable").appendText("CREATE TABLE test_table (id serial,data int)").build()
+ .createQuery("insertData").appendText("INSERT INTO test_table (data) VALUES (0)").build()
+ .createQuery("queryFail").appendText("update test_table tt set tt.data=10/(SELECT sum(t1.data) FROM test_table t1)").build()
+ .build()
+ .build();
+
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(store.getQueryExecutorContext());
+ exe.executeUpdate(connection, "junit.createTable");
+ exe.executeUpdate(connection, "junit.insertData");
+ exe.executeUpdate(connection, "junit.queryFail"); // runtime data failure, as prepared will go correctly
+ }
+ }
+
+ @Test(expected=SQLExceptionRuntime.class)
+ public void testExecuteSelectFail() throws Exception {
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+
+ TPQManager store = TPQFactory
+ .createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem")
+ .setLanguage(TPQFactory.StatementLanguage.SQL)
+ .createQuery("createTable").appendText("CREATE TABLE test_table (id serial,data int)").build()
+ .createQuery("insertData").appendText("INSERT INTO test_table (data) VALUES (0)").build()
+ .createQuery("queryFail").appendText("select tt.* from test_table tt where tt.data=10/(SELECT sum(t1.data) FROM test_table t1)").build()
+ .build()
+ .build();
+
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(store.getQueryExecutorContext());
+ exe.executeUpdate(connection, "junit.createTable");
+ exe.executeUpdate(connection, "junit.insertData");
+ exe.execute(connection, "junit.queryFail"); // runtime data failure, as prepared will go correctly
+ }
+ }
+
+ @Test(expected=SQLExceptionRuntime.class)
+ public void testExecuteSelectFailPrepare() throws Exception {
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+ TPQManager store = TPQFactory.createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem:testcaseFail")
+ .setLanguage(TPQFactory.StatementLanguage.SQL)
+ .createQuery("sql-fail").appendText("select * from article").build()
+ .build()
+ .build();
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(store.getQueryExecutorContext());
+ exe.execute(connection, "junit.sql-fail");
+ }
+ }
+
+ @Test(expected=SQLExceptionRuntime.class)
+ public void testTimeoutFail() throws Exception {
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+ TPQManager store = TPQFactory.createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem:test")
+ .setLanguage(TPQFactory.StatementLanguage.SQL)
+ .createQuery("createTable").appendText("CREATE TABLE test_table (id serial,data int)").build()
+ .createQuery("test").appendText("select * from test_table").build()
+ .build()
+ .build();
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(store.getQueryExecutorContext());
+ exe.executeUpdate(connection, "junit.createTable");
+ PreparedStatement ps = exe.createPreparedStatement(connection, "junit.test", null);
+ ps.close();
+ exe.prepareTimeout(ps, 123);
+ }
+ }
+
+ @Test(expected=SQLExceptionRuntime.class)
+ public void testParameterFail() throws Exception {
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+ TPQManager store = TPQFactory.createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem:test")
+ .setLanguage(TPQFactory.StatementLanguage.SQL)
+ .createQuery("createTable").appendText("CREATE TABLE test_table (id serial,data int)").build()
+ .createQuery("test").appendText("select * from test_table").build()
+ .build()
+ .build();
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(store.getQueryExecutorContext());
+ exe.executeUpdate(connection, "junit.createTable");
+ PreparedStatement ps = exe.createPreparedStatement(connection, "junit.test", null);
+ exe.prepareParameterValue(ps, 1, 123);
+ }
+ }
+
+ @Test
+ public void testExecuteBig() throws Exception {
+ int sizeFactor = 1;
+ try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;")) {
+ TPQManager queryStore = TPQFactory.createManagerBuilder().readQuerySet("net/forwardfire/tpquery/executor/jdbc/test-big.xml").build();
+ TPQExecutorJdbc exe = new TPQExecutorJdbc(queryStore.getQueryExecutorContext());
+ //Thread.sleep(1000*5);
+
+ System.out.println("Creating big table...");
+ int insertCount = exe.executeUpdate(connection, "TestBig.createTable");
+ assertEquals(0,insertCount);
+
+ System.out.println("Creating big test table data...");
+ Map testData = new HashMap();
+ for (int i=0;i<50*sizeFactor;i++) {
+ testData.put("id", i);
+ for (int c=0;c<100;c++) {
+ String colName = String.format("col%03d", c);
+ testData.put(colName, ""+i+c);
+ }
+ insertCount = exe.executeUpdate(connection, "TestBig.insert",testData);
+ assertEquals(1,insertCount);
+ }
+
+ System.out.println("Selecting big test table data...");
+ int rows = 0;
+ testData = new HashMap();
+ for (int i=1;i<30*sizeFactor;i++) {
+ testData.put("col001", ""+1*i);
+ testData.put("col002", ""+2+i);
+ testData.put("col003", ""+3/i);
+ testData.put("col004", ""+4+i);
+ testData.put("col005", ""+5/i);
+ testData.put("col006", ""+6*i);
+ testData.put("col007", ""+7+i);
+ testData.put("col008", ""+8/i);
+ testData.put("col009", ""+9*i);
+ testData.put("col000", ""+0+i);
+ PreparedStatement ps = exe.execute(connection, "TestBig.getBy10Cols", testData);
+ //ps.getParameterMetaData();
+ ResultSet rs = ps.getResultSet();
+ while (rs.next()) {
+ rows++;
+ }
+ }
+
+ System.out.println("Done...rows: "+rows);
+ }
+ }
+
+ private void printData(PreparedStatement ps) throws SQLException {
+ ResultSet rs = ps.getResultSet();
+ ps.getParameterMetaData();
+
+ while (rs.next()) {
+ System.out.println("data record:");
+ for (int i=1;i<=ps.getMetaData().getColumnCount();i++) {
+ String name = ps.getMetaData().getColumnName(i);
+ Object value = rs.getObject(i);
+ System.out.println("column: "+name+" value: "+value);
+ }
+ }
+ }
+}
diff --git a/tpquery-executor-jdbc/src/test/resources/net/forwardfire/tpquery/executor/jdbc/test-big.xml b/tpquery-executor-jdbc/src/test/resources/net/forwardfire/tpquery/executor/jdbc/test-big.xml
new file mode 100644
index 0000000..310d74b
--- /dev/null
+++ b/tpquery-executor-jdbc/src/test/resources/net/forwardfire/tpquery/executor/jdbc/test-big.xml
@@ -0,0 +1,289 @@
+
+
+
+ CREATE TABLE test_big (
+ id serial,
+ col000 text,col001 text,col002 text,col003 text,col004 text,col005 text,col006 text,col007 text,col008 text,col009 text,
+ col010 text,col011 text,col012 text,col013 text,col014 text,col015 text,col016 text,col017 text,col018 text,col019 text,
+ col020 text,col021 text,col022 text,col023 text,col024 text,col025 text,col026 text,col027 text,col028 text,col029 text,
+ col030 text,col031 text,col032 text,col033 text,col034 text,col035 text,col036 text,col037 text,col038 text,col039 text,
+ col040 text,col041 text,col042 text,col043 text,col044 text,col045 text,col046 text,col047 text,col048 text,col049 text,
+ col050 text,col051 text,col052 text,col053 text,col054 text,col055 text,col056 text,col057 text,col058 text,col059 text,
+ col060 text,col061 text,col062 text,col063 text,col064 text,col065 text,col066 text,col067 text,col068 text,col069 text,
+ col070 text,col071 text,col072 text,col073 text,col074 text,col075 text,col076 text,col077 text,col078 text,col079 text,
+ col080 text,col081 text,col082 text,col083 text,col084 text,col085 text,col086 text,col087 text,col088 text,col089 text,
+ col090 text,col091 text,col092 text,col093 text,col094 text,col095 text,col096 text,col097 text,col098 text,col099 text
+ )
+
+
+
+ Tests insert parameters as raw
+ INSERT INTO test_big ($$col_names$$) VALUES ($$col_values$$)
+
+
+
+
+ INSERT INTO test_big (
+ id,
+ $$inc:TestBig.inc.select.col00X$$ ,
+ $$inc:TestBig.inc.select.col01X$$ ,
+ $$inc:TestBig.inc.select.col02X$$ ,
+ $$inc:TestBig.inc.select.col03X$$ ,
+ $$inc:TestBig.inc.select.col04X$$ ,
+ $$inc:TestBig.inc.select.col05X$$ ,
+ $$inc:TestBig.inc.select.col06X$$ ,
+ $$inc:TestBig.inc.select.col07X$$ ,
+ $$inc:TestBig.inc.select.col08X$$ ,
+ $$inc:TestBig.inc.select.col09X$$
+ ) VALUES (
+ $$id$$ ,
+ $$col000$$ ,$$col001$$ ,$$col002$$ ,$$col003$$ ,$$col004$$ ,$$col005$$ ,$$col006$$ ,$$col007$$ ,$$col008$$ ,$$col009$$ ,
+ $$col010$$ ,$$col011$$ ,$$col012$$ ,$$col013$$ ,$$col014$$ ,$$col015$$ ,$$col016$$ ,$$col017$$ ,$$col018$$ ,$$col019$$ ,
+ $$col020$$ ,$$col021$$ ,$$col022$$ ,$$col023$$ ,$$col024$$ ,$$col025$$ ,$$col026$$ ,$$col027$$ ,$$col028$$ ,$$col029$$ ,
+ $$col030$$ ,$$col031$$ ,$$col032$$ ,$$col033$$ ,$$col034$$ ,$$col035$$ ,$$col036$$ ,$$col037$$ ,$$col038$$ ,$$col039$$ ,
+ $$col040$$ ,$$col041$$ ,$$col042$$ ,$$col043$$ ,$$col044$$ ,$$col045$$ ,$$col046$$ ,$$col047$$ ,$$col048$$ ,$$col049$$ ,
+ $$col050$$ ,$$col051$$ ,$$col052$$ ,$$col053$$ ,$$col054$$ ,$$col055$$ ,$$col056$$ ,$$col057$$ ,$$col058$$ ,$$col059$$ ,
+ $$col060$$ ,$$col061$$ ,$$col062$$ ,$$col063$$ ,$$col064$$ ,$$col065$$ ,$$col066$$ ,$$col067$$ ,$$col068$$ ,$$col069$$ ,
+ $$col070$$ ,$$col071$$ ,$$col072$$ ,$$col073$$ ,$$col074$$ ,$$col075$$ ,$$col076$$ ,$$col077$$ ,$$col078$$ ,$$col079$$ ,
+ $$col080$$ ,$$col081$$ ,$$col082$$ ,$$col083$$ ,$$col084$$ ,$$col085$$ ,$$col086$$ ,$$col087$$ ,$$col088$$ ,$$col089$$ ,
+ $$col090$$ ,$$col091$$ ,$$col092$$ ,$$col093$$ ,$$col094$$ ,$$col095$$ ,$$col096$$ ,$$col097$$ ,$$col098$$ ,$$col099$$
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $$inc:TestBig.inc.selectWhere$$
+ $$inc:TestBig.inc.orderBy$$
+
+
+
+
+ $$inc:TestBig.inc.selectWhere$$
+ $$inc:TestBig.inc.where.col000$$
+ $$inc:TestBig.inc.where.col001$$
+ $$inc:TestBig.inc.where.col002$$
+ $$inc:TestBig.inc.where.col003$$
+ $$inc:TestBig.inc.where.col004$$
+ $$inc:TestBig.inc.where.col005$$
+ $$inc:TestBig.inc.where.col006$$
+ $$inc:TestBig.inc.where.col007$$
+ $$inc:TestBig.inc.where.col008$$
+ $$inc:TestBig.inc.where.col009$$
+ $$inc:TestBig.inc.orderBy$$
+
+
+
+
+
+ col000,col001,col002,col003,col004,col005,col006,col007,col008,col009
+
+
+ col010,col011,col012,col013,col014,col015,col016,col017,col018,col019
+
+
+ col020,col021,col022,col023,col024,col025,col026,col027,col028,col029
+
+
+ col030,col031,col032,col033,col034,col035,col036,col037,col038,col039
+
+
+ col040,col041,col042,col043,col044,col045,col046,col047,col048,col049
+
+
+ col050,col051,col052,col053,col054,col055,col056,col057,col058,col059
+
+
+ col060,col061,col062,col063,col064,col065,col066,col067,col068,col069
+
+
+ col070,col071,col072,col073,col074,col075,col076,col077,col078,col079
+
+
+ col080,col081,col082,col083,col084,col085,col086,col087,col088,col089
+
+
+ col090,col091,col092,col093,col094,col095,col096,col097,col098,col099
+
+
+
+
+ SELECT
+ id,
+ $$inc:TestBig.inc.select.col00X$$ ,
+ $$inc:TestBig.inc.select.col01X$$ ,
+ $$inc:TestBig.inc.select.col02X$$ ,
+ $$inc:TestBig.inc.select.col03X$$ ,
+ $$inc:TestBig.inc.select.col04X$$ ,
+ $$inc:TestBig.inc.select.col05X$$ ,
+ $$inc:TestBig.inc.select.col06X$$ ,
+ $$inc:TestBig.inc.select.col07X$$ ,
+ $$inc:TestBig.inc.select.col08X$$ ,
+ $$inc:TestBig.inc.select.col09X$$
+ FROM
+ test_big
+ WHERE
+ true=true
+
+
+
+
+ AND col000 = $$col000$$
+
+
+
+ AND col001 = $$col001$$
+
+
+
+ AND col002 = $$col002$$
+
+
+
+ AND col003 = $$col003$$
+
+
+
+ AND col004 = $$col004$$
+
+
+
+ AND col005 = $$col005$$
+
+
+
+ AND col006 = $$col006$$
+
+
+
+ AND col007 = $$col007$$
+
+
+
+ AND col008 = $$col008$$
+
+
+
+ AND col009 = $$col009$$
+
+
+
+
+ ORDER BY $$orderColumn$$ $$orderDirection$$
+
+
+
+
+
+
+
diff --git a/tpquery-executor-jpa/pom.xml b/tpquery-executor-jpa/pom.xml
new file mode 100644
index 0000000..defba77
--- /dev/null
+++ b/tpquery-executor-jpa/pom.xml
@@ -0,0 +1,39 @@
+
+ 4.0.0
+
+ net.forwardfire.tpquery
+ tpquery
+ 0.0.1-SNAPSHOT
+
+ tpquery-executor-jpa
+
+
+ net.forwardfire.tpquery
+ tpquery-store
+ ${project.version}
+ compile
+
+
+ org.hibernate
+ hibernate-entitymanager
+ test
+
+
+ org.hibernate
+ hibernate-validator
+ test
+
+
+ org.apache.tomcat
+ tomcat-jasper-el
+ test
+
+
+
+ javax
+ javaee-api
+ provided
+
+
+
\ No newline at end of file
diff --git a/tpquery-executor-jpa/src/main/java/net/forwardfire/tpquery/store/executor/jpa/TPQExecutorJpa.java b/tpquery-executor-jpa/src/main/java/net/forwardfire/tpquery/store/executor/jpa/TPQExecutorJpa.java
new file mode 100644
index 0000000..91d48a8
--- /dev/null
+++ b/tpquery-executor-jpa/src/main/java/net/forwardfire/tpquery/store/executor/jpa/TPQExecutorJpa.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.store.executor.jpa;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import net.forwardfire.tpquery.TPQFactory;
+import net.forwardfire.tpquery.store.executor.AbstractTPQExecutor;
+import net.forwardfire.tpquery.store.executor.TPQExecutorContext;
+
+public class TPQExecutorJpa extends AbstractTPQExecutor {
+
+ private static final String HINT_TIMEOUT = "javax.persistence.query.timeout";
+
+ public TPQExecutorJpa(TPQExecutorContext context) {
+ super(context);
+ registrateStatementCreator(TPQFactory.StatementLanguage.HQL, (em,stmt) -> em.createQuery(stmt));
+ registrateStatementCreator(TPQFactory.StatementLanguage.SQL, (em,stmt) -> em.createNativeQuery(stmt));
+ }
+
+ @SuppressWarnings("unchecked")
+ public List selectList(EntityManager entityManager,String queryName,Map parameters) {
+ return createPreparedStatement(entityManager, queryName, parameters).getResultList();
+ }
+
+ @SuppressWarnings("unchecked")
+ public E selectObject(EntityManager entityManager,String queryName,Map parameters) {
+ return (E)createPreparedStatement(entityManager, queryName, parameters).getSingleResult();
+ }
+
+ @Override
+ protected int executeUpdate(Query persistenceQuery) {
+ return persistenceQuery.executeUpdate();
+ }
+
+ @Override
+ protected void prepareParameterValue(Query persistenceQuery, int index,Object value) {
+ persistenceQuery.setParameter(index,value);
+ }
+
+ @Override
+ protected void prepareTimeout(Query persistenceQuery, Integer timeout) {
+ persistenceQuery.setHint(HINT_TIMEOUT, timeout);
+ }
+}
diff --git a/tpquery-executor-jpa/src/main/java/net/forwardfire/tpquery/store/executor/jpa/package-info.java b/tpquery-executor-jpa/src/main/java/net/forwardfire/tpquery/store/executor/jpa/package-info.java
new file mode 100644
index 0000000..f2fa229
--- /dev/null
+++ b/tpquery-executor-jpa/src/main/java/net/forwardfire/tpquery/store/executor/jpa/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Persistance executor.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.store.executor.jpa;
diff --git a/tpquery-executor-jpa/src/test/java/net/forwardfire/tpquery/store/executor/jpa/TPQExecutorJpaTest.java b/tpquery-executor-jpa/src/test/java/net/forwardfire/tpquery/store/executor/jpa/TPQExecutorJpaTest.java
new file mode 100644
index 0000000..8e99d26
--- /dev/null
+++ b/tpquery-executor-jpa/src/test/java/net/forwardfire/tpquery/store/executor/jpa/TPQExecutorJpaTest.java
@@ -0,0 +1,229 @@
+package net.forwardfire.tpquery.store.executor.jpa;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+import net.forwardfire.tpquery.TPQManager;
+import net.forwardfire.tpquery.TPQFactory;
+import net.forwardfire.tpquery.config.TPQConfig;
+import net.forwardfire.tpquery.statement.AbstractTPQStatementWriter;
+import net.forwardfire.tpquery.statement.TPQStatementWriter;
+import net.forwardfire.tpquery.statement.language.TPQStatementLanguage;
+import net.forwardfire.tpquery.store.executor.jpa.TPQExecutorJpa;
+import net.forwardfire.tpquery.store.proxy.TPQueryName;
+import net.forwardfire.tpquery.store.proxy.TPQueryProxyFactory;
+import net.forwardfire.tpquery.store.proxy.TPQueryParameterName;
+import net.forwardfire.tpquery.store.proxy.TPQueryProxy;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+
+public class TPQExecutorJpaTest {
+
+ private EntityManagerFactory emFactory;
+ private EntityManager em = null;
+
+ @BeforeClass
+ public static void setupLogging() {
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+ lc.reset(); // disable logging
+ }
+
+ @Before
+ public void before() {
+ emFactory = Persistence.createEntityManagerFactory("junit");
+ em = emFactory.createEntityManager();
+ }
+
+ @After
+ public void close() {
+ em.close();
+ emFactory.close();
+ }
+
+ @Test
+ public void simple() throws Exception {
+
+ TestEntity t = new TestEntity();
+ t.active = true;
+ t.name = "test";
+ t.description = "junit test 012345678901234567890123456789";
+
+ em.getTransaction().begin();
+ em.persist(t);
+ em.getTransaction().commit();
+
+ TPQManager store = TPQFactory.createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem")
+ .setLanguage(TPQFactory.StatementLanguage.HQL)
+ .createQuery("test-select-sql")
+ .setLanguage("SQL")
+ .setTimeout(2000)
+ .appendText("SELECT * from TestEntity")
+ .build()
+ .createQuery("test-select").appendText("from TestEntity").build()
+ .createQuery("test-select-single")
+ .appendText("from TestEntity te where te.name=")
+ .appendParameter("name")
+ .createQueryParameter("name","text").build()
+ .build()
+ .createQuery("test-update")
+ .appendText("update TestEntity te set te.name=")
+ .appendParameter("name")
+ .createQueryParameter("name","text").build()
+ .build()
+ .build()
+ .build();
+
+ TPQExecutorJpa exe = new TPQExecutorJpa(store.getQueryExecutorContext());
+
+ //TQueryPrepared p = store.getQueryExecutorContext().prepareQuery("junit.test", null);
+ //Query q = em.createQuery(p.getStatement());
+ //q.getSingleResult();
+ //q.getResultList();
+
+ List resultSql = exe.selectList(em, "junit.test-select-sql", null);
+ assertNotNull(resultSql);
+ assertFalse(resultSql.isEmpty());
+
+ List result = exe.selectList(em, "junit.test-select", null);
+ assertNotNull(result);
+ assertFalse(result.isEmpty());
+
+ Map para = new HashMap<>();
+ para.put("name", "foobar");
+ em.getTransaction().begin();
+ int updateResult = exe.executeUpdate(em, "junit.test-update", para);
+ em.getTransaction().commit();
+ assertEquals(1,updateResult);
+
+ TestEntity resultSingle = exe.selectObject(em, "junit.test-select-single", para);
+ assertNotNull(resultSingle);
+ //assertEquals("foobar",resultSingle.name);
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testUnsupportedLanguage() throws Exception {
+ TPQConfig config = new TPQConfig();
+ config.addStatementLanguage(new TPQStatementLanguage() {
+ @Override
+ public String getLanguageType() {
+ return "XQL";
+ }
+
+ @Override
+ public TPQStatementWriter createQueryWriter(Map parameterData) {
+ return new AbstractTPQStatementWriter(parameterData) {
+ };
+ }
+ });
+ TPQManager store = TPQFactory
+ .createManagerBuilder(config)
+ .createQuerySet("junit", "jar:mem:test")
+ .createQuery("test")
+ .setLanguage("XQL")
+ .parseStatement("select * from table")
+ .build()
+ .build()
+ .build();
+ TPQExecutorJpa exe = new TPQExecutorJpa(store.getQueryExecutorContext());
+ exe.selectList(em, "junit.test", null);
+ }
+
+ @Test()
+ public void testQueryProxy() throws Exception {
+ TPQManager store = TPQFactory.createManagerBuilder()
+ .createQuerySet("junit", "jar:junit:mem")
+ .setLanguage(TPQFactory.StatementLanguage.HQL)
+ .createQuery("testSelect").appendText("from TestEntity").build()
+ .createQuery("testSelectSingle")
+ .appendText("from TestEntity te where te.name=")
+ .appendParameter("name")
+ .createQueryParameter("name","text").build()
+ .build()
+ .createQuery("testSelectMultiple")
+ .appendText("from TestEntity te where te.name=")
+ .appendParameter("name")
+ .appendText(" and length(te.name) > ")
+ .appendParameter("minLength")
+ .createQueryParameter("name","text").build()
+ .createQueryParameter("minLength","int").build()
+ .build()
+ .createQuery("testUpdate")
+ .appendText("update TestEntity te set te.name=")
+ .appendParameter("name")
+ .createQueryParameter("name","text").build()
+ .build()
+ .createQuerySetTree("TestEntityFooBarDataService")
+ .createQuery("testFoo").appendText("from TestEntity").build()
+ .buildTree()
+ .build()
+ .build();
+ TPQExecutorJpa exe = new TPQExecutorJpa(store.getQueryExecutorContext());
+
+
+ TPQueryProxyFactory proxy = new TPQueryProxyFactory();
+ proxy.registrateResultHandler(Object.class, (queryName,parameters) -> exe.selectObject (em, queryName, parameters));
+ proxy.registrateResultHandler(List.class, (queryName,parameters) -> exe.selectList (em, queryName, parameters));
+ proxy.registrateResultHandler(void.class, (queryName,parameters) -> exe.executeUpdate(em, queryName, parameters));
+ proxy.registrateResultHandler(int.class, (queryName,parameters) -> exe.executeUpdate(em, queryName, parameters));
+ proxy.registrateResultHandler(Integer.class, (queryName,parameters) -> exe.executeUpdate(em, queryName, parameters));
+
+ TestEntityDataService dataService = proxy.newProxyInstance(TestEntityDataService.class);
+ TestEntityFooBarDataService foobarService = proxy.newProxyInstance(TestEntityFooBarDataService.class);
+
+ List d = dataService.testSelect();
+ assertNotNull(d);
+
+ d = dataService.testSelectMultiple(1,"abc1");
+ d = dataService.testSelectMultiple(2,"abc2");
+ d = dataService.testSelectMultiple(3,"abc3");
+ assertNotNull(d);
+
+ d = foobarService.testFoo();
+ assertNotNull(d);
+ }
+
+ @TPQueryProxy(prefix="junit.")
+ public interface TestEntityDataService {
+
+ List testSelect();
+
+ @TPQueryName("testSelectSingle")
+ TestEntity testSelectSingle(
+ @TPQueryParameterName("name")
+ String name
+ );
+
+ List testSelectMultiple(
+ @TPQueryParameterName("minLength")
+ int length,
+ @TPQueryParameterName("name")
+ String name
+ );
+
+ void testUpdate(@TPQueryParameterName("name")String name);
+ }
+
+ @TPQueryProxy(prefix="junit.%s.")
+ interface TestEntityFooBarDataService {
+
+ @TPQueryName()
+ List testFoo();
+ }
+}
diff --git a/tpquery-executor-jpa/src/test/java/net/forwardfire/tpquery/store/executor/jpa/TestEntity.java b/tpquery-executor-jpa/src/test/java/net/forwardfire/tpquery/store/executor/jpa/TestEntity.java
new file mode 100644
index 0000000..5256c4d
--- /dev/null
+++ b/tpquery-executor-jpa/src/test/java/net/forwardfire/tpquery/store/executor/jpa/TestEntity.java
@@ -0,0 +1,31 @@
+package net.forwardfire.tpquery.store.executor.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+
+import org.hibernate.validator.constraints.Length;
+import org.hibernate.validator.constraints.NotEmpty;
+
+
+@Entity
+public class TestEntity {
+
+ @Id
+ @GeneratedValue
+ Long id;
+
+ @Column(nullable=false)
+ @NotNull
+ Boolean active;
+
+ @NotEmpty
+ @Column(unique = true)
+ String name;
+
+ @NotNull
+ @Length(min = 30, max=200)
+ String description;
+}
diff --git a/tpquery-executor-jpa/src/test/resources/META-INF/persistence.xml b/tpquery-executor-jpa/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..e8ef7be
--- /dev/null
+++ b/tpquery-executor-jpa/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,18 @@
+
+
+
+ net.forwardfire.tpquery.store.executor.jpa.TestEntity
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tpquery-store/pom.xml b/tpquery-store/pom.xml
new file mode 100644
index 0000000..3d5bb67
--- /dev/null
+++ b/tpquery-store/pom.xml
@@ -0,0 +1,22 @@
+
+ 4.0.0
+
+ net.forwardfire.tpquery
+ tpquery
+ 0.0.1-SNAPSHOT
+
+ tpquery-store
+
+
+ org.slf4j
+ slf4j-api
+ compile
+
+
+ org.apache.commons
+ commons-lang3
+ compile
+
+
+
\ No newline at end of file
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/TPQFactory.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/TPQFactory.java
new file mode 100644
index 0000000..5993dc0
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/TPQFactory.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.JDBCType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.script.Compilable;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.config.TPQConfig;
+import net.forwardfire.tpquery.config.TPQConfigInitializer;
+import net.forwardfire.tpquery.config.TPQConfigParameterValueHolder;
+import net.forwardfire.tpquery.config.TPQConfigParameterValueScripterObjectOrList;
+import net.forwardfire.tpquery.config.builder.TPQConfigBuilder;
+import net.forwardfire.tpquery.statement.language.TPQStatementLanguageHql;
+import net.forwardfire.tpquery.statement.language.TPQStatementLanguageSql;
+import net.forwardfire.tpquery.statement.parameter.TPQStatementParameterList;
+import net.forwardfire.tpquery.statement.parameter.TPQStatementParameterRaw;
+import net.forwardfire.tpquery.statement.parameter.TPQStatementParameterValue;
+import net.forwardfire.tpquery.store.TPQueryStoreScriptEngine;
+import net.forwardfire.tpquery.store.manager.TPQStoreManager;
+import net.forwardfire.tpquery.store.manager.TPQStoreManagerStatementCache;
+
+/**
+ * The tpquery factory to create objects.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+public final class TPQFactory {
+
+ private static final String DEFAULT_TREEPATH_SEPERATOR = ".";
+ private static final Boolean DEFAULT_PARAMETER_NULLABLE = false;
+ private static final String DEFAULT_SCRIPT_ENGINE_MINE_TYPE = "text/javascript";
+ private static final List DEFAULT_CONFIG_INITIALIZERS = Collections.unmodifiableList(Arrays.asList(
+ new StatementLanguage(),
+ new StatementParameter(),
+ new ParameterValueTypeAlias(),
+ new ParameterValueFunction(),
+ new TPQConfigInitializer() {
+ @Override
+ public void initializeConfig(TPQConfig config) {
+ // temp here move to better place.
+ config.setTreePathSeperator(TPQFactory.DEFAULT_TREEPATH_SEPERATOR);
+ config.setDefaultParameterNullable(DEFAULT_PARAMETER_NULLABLE);
+ config.setDefaultParameterType(TPQFactory.StatementParameter.VALUE);
+ config.setStatementCache(new TPQStoreManagerStatementCache());
+ }
+ }
+ ));
+
+ protected TPQFactory() {
+ }
+
+ /**
+ * Creates a default config.
+ * @return The config.
+ */
+ public static TPQConfig createConfig() {
+ return createConfig(DEFAULT_CONFIG_INITIALIZERS);
+ }
+
+ /**
+ * Creates a empty config and the inits by the configInit list.
+ * @param configInit The config initializers.
+ * @return The config.
+ */
+ public static TPQConfig createConfig(List configInit) {
+ TPQConfig config = new TPQConfig();
+ configInit.forEach(ci -> ci.initializeConfig(config));
+ return config;
+ }
+
+ /**
+ * Creates a manager from the config.
+ * @param config The config for the manager.
+ * @return The manager.
+ */
+ public static TPQManager createManager(TPQConfig config) {
+ return new TPQStoreManager(config);
+ }
+
+ // ----- builders
+
+ /**
+ * Create a builder that returns a manager.
+ * @return The builder.
+ * @throws JAXBException If the jaxb marshaller throws an error.
+ */
+ public static TPQConfigBuilder createManagerBuilder() throws JAXBException {
+ return createManagerBuilder(createConfig());
+ }
+
+ /**
+ * Create a builder that returns a manager.
+ * @param config The config to build.
+ * @return The builder.
+ * @throws JAXBException If the jaxb marshaller throws an error.
+ */
+ public static TPQConfigBuilder createManagerBuilder(TPQConfig config) throws JAXBException {
+ return new TPQConfigBuilder(config,() -> createManager(config));
+ }
+
+ /**
+ * Create a builder that returns the config.
+ * @return The builder.
+ * @throws JAXBException If the jaxb marshaller throws an error.
+ */
+ public static TPQConfigBuilder createConfigBuilder() throws JAXBException {
+ return createConfigBuilder(createConfig());
+ }
+
+ /**
+ * Create a builder that returns the config.
+ * @param config The config to build.
+ * @return The builder.
+ * @throws JAXBException If the jaxb marshaller throws an error.
+ */
+ public static TPQConfigBuilder createConfigBuilder(TPQConfig config) throws JAXBException {
+ return new TPQConfigBuilder(config,() -> config);
+ }
+
+ // ----- classes
+
+ public static final class StatementLanguage implements TPQConfigInitializer {
+
+ public static final String SQL = "SQL";
+ public static final String HQL = "HQL";
+
+ private StatementLanguage() {
+ }
+
+ @Override
+ public void initializeConfig(TPQConfig config) {
+ config.addStatementLanguage(new TPQStatementLanguageSql(SQL));
+ config.addStatementLanguage(new TPQStatementLanguageHql(HQL));
+ }
+ }
+
+ public static final class StatementParameter implements TPQConfigInitializer {
+ public static final String VALUE = "VALUE";
+ public static final String LIST = "LIST";
+ public static final String RAW = "RAW";
+ public static final String RAW_NULL = "RAW_NULL";
+
+ private StatementParameter() {
+ }
+
+ @Override
+ public void initializeConfig(TPQConfig config) {
+ config.addStatementParameter(new TPQStatementParameterValue(VALUE));
+ config.addStatementParameter(new TPQStatementParameterList(LIST));
+ config.addStatementParameter(new TPQStatementParameterRaw(RAW,""));
+ config.addStatementParameter(new TPQStatementParameterRaw(RAW_NULL,"null"));
+ }
+ }
+
+ public static final class ParameterValueType {
+ // java type
+ public static final String JAVA_OBJECT = Object.class.getName();
+ public static final String BIGDECIMAL = java.math.BigDecimal.class.getName();
+ public static final String BOOLEAN = Boolean.class.getName();
+ public static final String INTEGER = Integer.class.getName();
+ public static final String STRING = String.class.getName();
+ public static final String DOUBLE = Double.class.getName();
+ public static final String LONG = Long.class.getName();
+ public static final String FLOAT = Float.class.getName();
+ public static final String SHORT = Short.class.getName();
+ public static final String URL = java.net.URL.class.getName();
+ public static final String BYTE_DATA = byte[].class.getName();
+
+ // jdbc types
+ public static final String SQL_ARRAY = java.sql.Array.class.getName();
+ public static final String SQL_BLOB = java.sql.Blob.class.getName();
+ public static final String SQL_CLOB = java.sql.Clob.class.getName();
+ public static final String SQL_DATE = java.sql.Date.class.getName();
+ public static final String SQL_NCLOB = java.sql.NClob.class.getName();
+ public static final String SQL_REF = java.sql.Ref.class.getName();
+ public static final String SQL_ROWID = java.sql.RowId.class.getName();
+ public static final String SQL_STRUCT = java.sql.Struct.class.getName();
+ public static final String SQL_XML = java.sql.SQLXML.class.getName();
+ public static final String SQL_TIME = java.sql.Time.class.getName();
+ public static final String SQL_TIMESTAMP = java.sql.Timestamp.class.getName();
+
+ protected ParameterValueType() {
+ }
+ }
+
+ public static final class ParameterValueTypeAlias implements TPQConfigInitializer {
+ public static final String NUMERIC = "numeric";
+
+ public static final String SHORT = "short";
+ public static final String INT2 = "int2";
+ public static final String SMALLINT = "smallint";
+
+ public static final String INTEGER = "integer";
+ public static final String INT = "int";
+ public static final String INT4 = "int4";
+
+ public static final String LONG = "long";
+ public static final String INT8 = "int8";
+ public static final String BIGINT = "bigint";
+
+ public static final String BOOLEAN = "boolean";
+ public static final String BOOL = "bool";
+
+ public static final String FLOAT = "float";
+ public static final String FLOAT4 = "float4";
+ public static final String REAL = "real";
+
+ public static final String DOUBLE = "double";
+ public static final String FLOAT8 = "float8";
+ public static final String DOUBLE_PRECISION = "double precision";
+
+ public static final String STRING = "string";
+ public static final String TEXT = "text";
+ public static final String VARCHAR = "varchar";
+ public static final String LONGVARCHAR = "longvarchar";
+ public static final String CHARACTER_VARYING = "character varying";
+ public static final String CHAR = "char";
+ public static final String CHARACTER = "character";
+
+ public static final String DATE = "date";
+ public static final String TIME = "time";
+ public static final String TIMESTAMP = "timestamp";
+
+ private ParameterValueTypeAlias() {
+ }
+
+ @Override
+ public void initializeConfig(TPQConfig config) {
+ config.addValueTypeAlias(NUMERIC, ParameterValueType.BIGDECIMAL);
+
+ config.addValueTypeAlias(SHORT, ParameterValueType.SHORT);
+ config.addValueTypeAlias(INT2, ParameterValueType.SHORT);
+ config.addValueTypeAlias(SMALLINT, ParameterValueType.SHORT);
+
+ config.addValueTypeAlias(INTEGER, ParameterValueType.INTEGER);
+ config.addValueTypeAlias(INT, ParameterValueType.INTEGER);
+ config.addValueTypeAlias(INT4, ParameterValueType.INTEGER);
+
+ config.addValueTypeAlias(LONG, ParameterValueType.LONG);
+ config.addValueTypeAlias(INT8, ParameterValueType.LONG);
+ config.addValueTypeAlias(BIGINT, ParameterValueType.LONG);
+
+ config.addValueTypeAlias(BOOLEAN, ParameterValueType.BOOLEAN);
+ config.addValueTypeAlias(BOOL, ParameterValueType.BOOLEAN);
+
+ config.addValueTypeAlias(FLOAT, ParameterValueType.FLOAT);
+ config.addValueTypeAlias(FLOAT4, ParameterValueType.FLOAT);
+ config.addValueTypeAlias(REAL, ParameterValueType.FLOAT);
+
+ config.addValueTypeAlias(DOUBLE, ParameterValueType.DOUBLE);
+ config.addValueTypeAlias(DOUBLE_PRECISION, ParameterValueType.DOUBLE);
+ config.addValueTypeAlias(FLOAT8, ParameterValueType.DOUBLE);
+
+ config.addValueTypeAlias(STRING, ParameterValueType.STRING);
+ config.addValueTypeAlias(TEXT, ParameterValueType.STRING);
+ config.addValueTypeAlias(VARCHAR, ParameterValueType.STRING);
+ config.addValueTypeAlias(LONGVARCHAR, ParameterValueType.STRING);
+ config.addValueTypeAlias(CHARACTER_VARYING, ParameterValueType.STRING);
+ config.addValueTypeAlias(CHAR, ParameterValueType.STRING);
+ config.addValueTypeAlias(CHARACTER, ParameterValueType.STRING);
+
+ config.addValueTypeAlias(DATE, ParameterValueType.SQL_DATE);
+ config.addValueTypeAlias(TIME, ParameterValueType.SQL_TIME);
+ config.addValueTypeAlias(TIMESTAMP, ParameterValueType.SQL_TIMESTAMP);
+
+ // new jdbc names (missing; DISTINCT and REF_CURSOR)
+ config.addValueTypeAlias(JDBCType.ARRAY.name(), ParameterValueType.SQL_ARRAY);
+ config.addValueTypeAlias(JDBCType.BIGINT.name(), ParameterValueType.BIGDECIMAL);
+ config.addValueTypeAlias(JDBCType.BINARY.name(), ParameterValueType.BYTE_DATA);
+ config.addValueTypeAlias(JDBCType.BIT.name(), ParameterValueType.BOOLEAN);
+ config.addValueTypeAlias(JDBCType.BLOB.name(), ParameterValueType.SQL_BLOB);
+ config.addValueTypeAlias(JDBCType.BOOLEAN.name(), ParameterValueType.BOOLEAN);
+ config.addValueTypeAlias(JDBCType.CHAR.name(), ParameterValueType.STRING);
+ config.addValueTypeAlias(JDBCType.CLOB.name(), ParameterValueType.SQL_CLOB);
+ config.addValueTypeAlias(JDBCType.DATALINK.name(), ParameterValueType.URL);
+ config.addValueTypeAlias(JDBCType.DATE.name(), ParameterValueType.SQL_DATE);
+ config.addValueTypeAlias(JDBCType.DECIMAL.name(), ParameterValueType.BIGDECIMAL);
+ config.addValueTypeAlias(JDBCType.DOUBLE.name(), ParameterValueType.DOUBLE);
+ config.addValueTypeAlias(JDBCType.FLOAT.name(), ParameterValueType.FLOAT);
+ config.addValueTypeAlias(JDBCType.INTEGER.name(), ParameterValueType.INTEGER);
+ config.addValueTypeAlias(JDBCType.JAVA_OBJECT.name(), ParameterValueType.JAVA_OBJECT);
+ config.addValueTypeAlias(JDBCType.LONGNVARCHAR.name(), ParameterValueType.STRING);
+ config.addValueTypeAlias(JDBCType.LONGVARBINARY.name(), ParameterValueType.BYTE_DATA);
+ config.addValueTypeAlias(JDBCType.LONGVARCHAR.name(), ParameterValueType.STRING);
+ config.addValueTypeAlias(JDBCType.NCHAR.name(), ParameterValueType.STRING);
+ config.addValueTypeAlias(JDBCType.NCLOB.name(), ParameterValueType.SQL_NCLOB);
+ config.addValueTypeAlias(JDBCType.NULL.name(), ParameterValueType.JAVA_OBJECT);
+ config.addValueTypeAlias(JDBCType.NUMERIC.name(), ParameterValueType.BIGDECIMAL);
+ config.addValueTypeAlias(JDBCType.NVARCHAR.name(), ParameterValueType.STRING);
+ config.addValueTypeAlias(JDBCType.OTHER.name(), ParameterValueType.JAVA_OBJECT);
+ config.addValueTypeAlias(JDBCType.REAL.name(), ParameterValueType.FLOAT);
+ config.addValueTypeAlias(JDBCType.REF.name(), ParameterValueType.SQL_REF);
+ config.addValueTypeAlias(JDBCType.ROWID.name(), ParameterValueType.SQL_ROWID);
+ config.addValueTypeAlias(JDBCType.SMALLINT.name(), ParameterValueType.INTEGER);
+ config.addValueTypeAlias(JDBCType.SQLXML.name(), ParameterValueType.SQL_XML);
+ config.addValueTypeAlias(JDBCType.STRUCT.name(), ParameterValueType.SQL_STRUCT);
+ config.addValueTypeAlias(JDBCType.TIME.name(), ParameterValueType.SQL_TIME);
+ config.addValueTypeAlias(JDBCType.TIME_WITH_TIMEZONE.name(), ParameterValueType.SQL_TIME);
+ config.addValueTypeAlias(JDBCType.TIMESTAMP.name(), ParameterValueType.SQL_TIMESTAMP);
+ config.addValueTypeAlias(JDBCType.TIMESTAMP_WITH_TIMEZONE.name(), ParameterValueType.SQL_TIMESTAMP);
+ config.addValueTypeAlias(JDBCType.TINYINT.name(), ParameterValueType.SHORT);
+ config.addValueTypeAlias(JDBCType.VARBINARY.name(), ParameterValueType.BYTE_DATA);
+ config.addValueTypeAlias(JDBCType.VARCHAR.name(), ParameterValueType.STRING);
+
+ }
+ }
+
+ public static final class ParameterValueFunction implements TPQConfigInitializer {
+
+ private static final String NEW_PREFIX = "new ";
+ private static final String FUNCTION_PREFIX = "function ";
+ private static final String FUNCTION_ARGS_BEGIN = "(";
+ private static final String FUNCTION_ARGS_END = ")";
+ private static final String FUNCTION_ARGS_EMPTY = FUNCTION_ARGS_BEGIN+FUNCTION_ARGS_END;
+
+ public static final String CREATE_OBJECT = "createObject";
+ public static final String CREATE_ARRAY_LIST = "createArrayList";
+ public static final String CREATE_HASH_MAP = "createHashMap";
+ public static final String CREATE_OBJECT_LIST = "createObjectList";
+ public static final String CREATE_VALUE_HOLDER = "createValueHolder";
+ public static final String EPOCH = "epoch";
+ public static final String DATE = "date";
+ public static final String TIME = "time";
+ public static final String TIMESTAMP = "timestamp";
+
+ private ParameterValueFunction() {
+ }
+
+ @Override
+ public void initializeConfig(TPQConfig config) {
+
+ config.addParameterValueScript(FUNCTION_PREFIX
+ +CREATE_OBJECT+"(clazz,value) {\n"
+ +"\tif (value) {\n"
+ +"\t return "+NEW_PREFIX+"clazz(value);\n"
+ +"\t} else {\n"
+ +"\t return "+NEW_PREFIX+"clazz();\n"
+ +"\t}\n"
+ +"}\n");
+ config.addParameterValueScript(FUNCTION_PREFIX
+ +CREATE_OBJECT_LIST+"(clazz,value) {\n"
+ +"\tvar values = value.split(',');\n"
+ +"\tvar result = "+CREATE_ARRAY_LIST+"();\n"
+ +"\tfor (var i = 0; i < values.length; i++) {\n"
+ +"\t result.add("+CREATE_OBJECT+"(clazz,values[i]));\n"
+ +"\t}\n"
+ +"\treturn result;\n"
+ +"}\n");
+
+ config.addParameterValueScript(FUNCTION_PREFIX+CREATE_VALUE_HOLDER+"(value) { return new Packages."+TPQConfigParameterValueHolder.class.getName()+"(value); }");
+
+ config.addParameterValueScript(buildFunctionCreateObject(CREATE_ARRAY_LIST,ArrayList.class.getName()));
+ config.addParameterValueScript(buildFunctionCreateObject(CREATE_HASH_MAP,HashMap.class.getName()));
+
+ config.addParameterValueScript(buildFunctionReturn(EPOCH,System.class.getName()+".currentTimeMillis()"));
+ config.addParameterValueScript(buildFunctionEpochObject(DATE,ParameterValueType.SQL_DATE));
+ config.addParameterValueScript(buildFunctionEpochObject(TIME,ParameterValueType.SQL_TIME));
+ config.addParameterValueScript(buildFunctionEpochObject(TIMESTAMP,ParameterValueType.SQL_TIMESTAMP));
+
+ config.setParameterValueEngine(createScriptEngine());
+ config.setParameterValueScripter(new TPQConfigParameterValueScripterObjectOrList());
+ }
+
+ private TPQueryStoreScriptEngine createScriptEngine() {
+ ScriptEngine engine = new ScriptEngineManager().getEngineByMimeType(DEFAULT_SCRIPT_ENGINE_MINE_TYPE);
+ Validate.isInstanceOf(Compilable.class, engine, "ScriptEngine does not implement Compilable interface.");
+ Validate.isInstanceOf(Invocable.class, engine, "ScriptEngine does not implement Invocable interface.");
+ return (TPQueryStoreScriptEngine) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{TPQueryStoreScriptEngine.class}, new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return method.invoke(engine, args);
+ }
+ });
+ }
+
+ private String buildFunctionReturn(String name,String body) {
+ return FUNCTION_PREFIX+name+FUNCTION_ARGS_EMPTY+" { return "+body+"; }";
+ }
+
+ private String buildFunctionEpochObject(String name,String epochClass) {
+ return buildFunctionReturn(name,NEW_PREFIX+epochClass+FUNCTION_ARGS_BEGIN+EPOCH+FUNCTION_ARGS_EMPTY+FUNCTION_ARGS_END);
+ }
+
+ private String buildFunctionCreateObject(String name,String className) {
+ return buildFunctionReturn(name,CREATE_OBJECT+FUNCTION_ARGS_BEGIN+className+FUNCTION_ARGS_END);
+ }
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/TPQManager.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/TPQManager.java
new file mode 100644
index 0000000..a0e01bc
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/TPQManager.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery;
+
+import net.forwardfire.tpquery.store.TPQueryStore;
+import net.forwardfire.tpquery.store.executor.TPQExecutorContext;
+
+/**
+ * The manager holds the query store and executor context.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Feb 14, 2015
+ */
+public interface TPQManager {
+
+ /**
+ * Returns the query store.
+ * @return The query store.
+ */
+ TPQueryStore getQueryStore();
+
+ /**
+ * Returns the query executor context.
+ * @return The query executor context.
+ */
+ TPQExecutorContext getQueryExecutorContext();
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/AbstractTPQConfig.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/AbstractTPQConfig.java
new file mode 100644
index 0000000..8a2e23d
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/AbstractTPQConfig.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.forwardfire.tpquery.config.validate.TPQConfigValidator;
+import net.forwardfire.tpquery.model.TPQuerySet;
+import net.forwardfire.tpquery.statement.language.TPQStatementLanguage;
+import net.forwardfire.tpquery.statement.parameter.TPQStatementParameter;
+import net.forwardfire.tpquery.store.TPQueryStoreScriptEngine;
+import net.forwardfire.tpquery.store.TPQueryStoreStatementCache;
+
+/**
+ * Abstract config data.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 25, 2015
+ */
+public abstract class AbstractTPQConfig {
+
+ protected String treePathSeperator;
+ protected String defaultParameterType;
+ protected Boolean defaultParameterNullable;
+ protected TPQueryStoreStatementCache statementCache;
+ protected TPQueryStoreScriptEngine parameterValueEngine;
+ protected TPQConfigParameterValueScripter parameterValueScripter;
+ protected final Map querySets;
+ protected final Map statementParameters;
+ protected final Map statementLanguages;
+ protected final Map valueTypeAliases;
+ protected final List configValidators;
+ protected final List parameterValueScripts;
+
+ protected AbstractTPQConfig() {
+ this(new HashMap<>(),new HashMap<>(),new HashMap<>(),new HashMap<>(),new ArrayList<>(),new ArrayList<>());
+ }
+
+ protected AbstractTPQConfig(
+ Map querySets,
+ Map statementParameters,
+ Map statementLanguages,
+ Map valueTypeAliases,
+ List configValidators,
+ List parameterValueScripts
+ ) {
+ this.querySets=querySets;
+ this.statementParameters=statementParameters;
+ this.statementLanguages=statementLanguages;
+ this.valueTypeAliases=valueTypeAliases;
+ this.configValidators=configValidators;
+ this.parameterValueScripts=parameterValueScripts;
+ }
+
+ /**
+ * @return the treePathSeperator
+ */
+ public String getTreePathSeperator() {
+ return treePathSeperator;
+ }
+
+ /**
+ * @return the defaultParameterType
+ */
+ public String getDefaultParameterType() {
+ return defaultParameterType;
+ }
+
+ /**
+ * @return the defaultParameterNullable
+ */
+ public Boolean getDefaultParameterNullable() {
+ return defaultParameterNullable;
+ }
+
+ /**
+ * @return the statementCache
+ */
+ public TPQueryStoreStatementCache getStatementCache() {
+ return statementCache;
+ }
+
+ /**
+ * @return the parameterValueEngine
+ */
+ public TPQueryStoreScriptEngine getParameterValueEngine() {
+ return parameterValueEngine;
+ }
+
+ /**
+ * @return the parameterValueScripter
+ */
+ public TPQConfigParameterValueScripter getParameterValueScripter() {
+ return parameterValueScripter;
+ }
+
+ /**
+ * @return the querySets
+ */
+ public Map getQuerySets() {
+ return querySets;
+ }
+
+ /**
+ * @return the statementParameters
+ */
+ public Map getStatementParameters() {
+ return statementParameters;
+ }
+
+ /**
+ * @return the statementLanguages
+ */
+ public Map getStatementLanguages() {
+ return statementLanguages;
+ }
+
+ /**
+ * @return the valueTypeAliases
+ */
+ public Map getValueTypeAliases() {
+ return valueTypeAliases;
+ }
+
+ /**
+ * @return the configValidators
+ */
+ public List getConfigValidators() {
+ return configValidators;
+ }
+
+ /**
+ * @return the parameterValueScripts
+ */
+ public List getParameterValueScripts() {
+ return parameterValueScripts;
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfig.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfig.java
new file mode 100644
index 0000000..01077d8
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfig.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config;
+
+import java.util.Map;
+
+import java.util.Objects;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.config.validate.TPQConfigValidator;
+import net.forwardfire.tpquery.config.validate.TPQConfigValidatorCheck;
+import net.forwardfire.tpquery.model.TPQuerySet;
+import net.forwardfire.tpquery.statement.language.TPQStatementLanguage;
+import net.forwardfire.tpquery.statement.parameter.TPQStatementParameter;
+import net.forwardfire.tpquery.store.TPQueryStoreScriptEngine;
+import net.forwardfire.tpquery.store.TPQueryStoreStatementCache;
+
+/**
+ * Holds the config to build the query manager.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 17, 2015
+ */
+public class TPQConfig extends AbstractTPQConfig {
+
+ /**
+ * Creates a empty TPQStore.
+ */
+ public TPQConfig() {
+ super();
+ }
+
+ /**
+ * @param treePathSeperator the treePathSeperator to set.
+ */
+ public void setTreePathSeperator(String treePathSeperator) {
+ this.treePathSeperator = Validate.notNull(treePathSeperator,"Can't set treePathSeperator to null");
+ }
+
+ /**
+ * @param defaultParameterType the defaultParameterType to set
+ */
+ public void setDefaultParameterType(String defaultParameterType) {
+ this.defaultParameterType = Validate.notNull(defaultParameterType,"Can't set defaultParameterType to null");
+ }
+
+ /**
+ * @param defaultParameterNullable the defaultParameterNullable to set
+ */
+ public void setDefaultParameterNullable(Boolean defaultParameterNullable) {
+ this.defaultParameterNullable = Validate.notNull(defaultParameterNullable,"Can't set defaultParameterNullable to null");
+ }
+
+ /**
+ * @param statementCache the statementCache to set
+ */
+ public void setStatementCache(TPQueryStoreStatementCache statementCache) {
+ this.statementCache = Validate.notNull(statementCache,"Can't set statementCache to null");
+ }
+
+ /**
+ * @param parameterValueScripter the parameterValueScripter to set
+ */
+ public void setParameterValueScripter(TPQConfigParameterValueScripter parameterValueScripter) {
+ this.parameterValueScripter = Validate.notNull(parameterValueScripter,"Can't set parameterValueScripter to null");
+ }
+
+ /**
+ * @param parameterValueEngine the parameterValueEngine to set
+ */
+ public void setParameterValueEngine(TPQueryStoreScriptEngine parameterValueEngine) {
+ this.parameterValueEngine = Validate.notNull(parameterValueEngine,"Can't set parameterValueEngine to null");
+ }
+
+ private void mapAdd(Map map,K key,V value) {
+ Validate.notNull(map);
+ Validate.notNull(key);
+ Validate.notNull(value);
+ Validate.isTrue(Objects.isNull(map.get(key)),"Cannot handle key twice: %s",key);
+ map.put(key, value);
+ }
+
+ private void mapRemove(Map map,K key) {
+ Validate.notNull(Validate.notNull(map).remove(Validate.notNull(key)),"No object for key %s",key);
+ }
+
+ /**
+ * Adds a query set.
+ * @param qs The query set to add.
+ * @param systemId The systemId from which the query set was loaded.
+ */
+ public void addQuerySet(String systemId,TPQuerySet qs) {
+ mapAdd(querySets, systemId, qs);
+ }
+
+ /**
+ * Removes a query set.
+ * @param systemId The systemId of the query set to remove.
+ */
+ public void removeQuerySet(String systemId) {
+ mapRemove(querySets,systemId);
+ }
+
+ /**
+ * Adds a statement parameter.
+ * @param statementParameter The statement parameter to add.
+ */
+ public void addStatementParameter(TPQStatementParameter statementParameter) {
+ mapAdd(statementParameters, statementParameter.getParameterType(), statementParameter);
+ }
+
+ /**
+ * Removes a statement parameter.
+ * @param statementParameterKey The parameter key.
+ */
+ public void removeStatementParameter(String statementParameterKey) {
+ mapRemove(statementParameters,statementParameterKey);
+ }
+
+ /**
+ * Adds a statement language.
+ * @param statementLanguage The statement language to add.
+ */
+ public void addStatementLanguage(TPQStatementLanguage statementLanguage) {
+ mapAdd(statementLanguages, statementLanguage.getLanguageType(), statementLanguage);
+ }
+
+ /**
+ * Removes a statement language.
+ * @param statementLanguageKey The statement language key.
+ */
+ public void removeStatementLanguage(String statementLanguageKey) {
+ mapRemove(statementLanguages, statementLanguageKey);
+ }
+
+ /**
+ * Adds a value alias.
+ * @param alias The alias to add.
+ * @param valueType The aliases valueType.
+ */
+ public void addValueTypeAlias(String alias,String valueType) {
+ mapAdd(valueTypeAliases, alias, valueType);
+ }
+
+ /**
+ * Remove a value type alias.
+ * @param alias The alias to remove.
+ */
+ public void removeValueTypeAlias(String alias) {
+ mapRemove(valueTypeAliases, alias);
+ }
+
+ /**
+ * Adds a config validator.
+ * @param namePattern The pattern where to check.
+ * @param validatorChecker The checker validator.
+ * @return The validator.
+ */
+ public TPQConfigValidator addConfigValidator(String namePattern,TPQConfigValidatorCheck validatorChecker) {
+ TPQConfigValidator result = new TPQConfigValidator(namePattern,validatorChecker); // validator does null check
+ configValidators.add(result);
+ return result;
+ }
+
+ /**
+ * Removes a config validator.
+ * @param validator The validator to remove.
+ */
+ public void removeConfigValidator(TPQConfigValidator validator) {
+ configValidators.remove(Validate.notNull(validator,"Can't remove null validator"));
+ }
+
+ /**
+ * Adds a value script.
+ * @param script The script to add.
+ */
+ public void addParameterValueScript(String script) {
+ parameterValueScripts.add(Validate.notNull(script,"Can't add null script."));
+ }
+
+ /**
+ * Removes a value script.
+ * @param script The script to remove.
+ */
+ public void removeParameterValueScript(String script) {
+ parameterValueScripts.remove(Validate.notNull(script,"Can't remove null script."));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigInitializer.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigInitializer.java
new file mode 100644
index 0000000..04af7e2
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigInitializer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config;
+
+/**
+ * Interface to split the config init over classes.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jun 1, 2015
+ */
+public interface TPQConfigInitializer {
+
+ /**
+ * init config.
+ * @param config The config to init.
+ */
+ void initializeConfig(TPQConfig config);
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueHolder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueHolder.java
new file mode 100644
index 0000000..5329ce8
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueHolder.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config;
+
+/**
+ * Caches a default value as a value so it only need to be resolved once.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 28, 2015
+ */
+public final class TPQConfigParameterValueHolder {
+
+ private final Object value;
+
+ /**
+ * Creates this value holder.
+ * @param value The value to hold.
+ */
+ public TPQConfigParameterValueHolder(Object value) {
+ this.value=value;
+ }
+
+ /**
+ * Returns the constant value.
+ * @return The value.
+ */
+ public Object getValue() {
+ return value;
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueScripter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueScripter.java
new file mode 100644
index 0000000..04f5e8d
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueScripter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config;
+
+import net.forwardfire.tpquery.model.TPQueryParameter;
+
+/**
+ * Convert a default value to a script to resolve the value as object.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 26, 2015
+ */
+public interface TPQConfigParameterValueScripter {
+
+ /**
+ * Convert the defaultValue to script form.
+ * @param queryParameter The query parameter to create de script for.
+ * @return The text of the script.
+ */
+ String convertDefaultValueToScript(TPQueryParameter queryParameter);
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueScripterObjectOrList.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueScripterObjectOrList.java
new file mode 100644
index 0000000..db5ab12
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/TPQConfigParameterValueScripterObjectOrList.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config;
+
+import net.forwardfire.tpquery.TPQFactory;
+import net.forwardfire.tpquery.model.TPQueryParameter;
+
+/**
+ * Can convert objects and list to a js script value.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 27, 2015
+ */
+public class TPQConfigParameterValueScripterObjectOrList implements TPQConfigParameterValueScripter {
+
+ protected static final String PREFIX_JS = "js:";
+
+ @Override
+ public String convertDefaultValueToScript(TPQueryParameter queryParameter) {
+ String defaultValue = queryParameter.getDefaultValue();
+ if (defaultValue.startsWith(PREFIX_JS)) {
+ return defaultValue.substring(PREFIX_JS.length());
+ } else {
+ return createDefaultValueToScript(queryParameter);
+ }
+ }
+
+ private String createDefaultValueToScript(TPQueryParameter queryParameter) {
+ // Create object function wrappers
+ String functionName = TPQFactory.ParameterValueFunction.CREATE_OBJECT;
+ if (TPQFactory.StatementParameter.LIST.equals(queryParameter.getType())) {
+ functionName = TPQFactory.ParameterValueFunction.CREATE_OBJECT_LIST;
+ }
+ String value = queryParameter.getDefaultValue().replaceAll("'", "\\\\'");
+ String function = functionName+"("+queryParameter.getValueType()+",'"+value+"')";
+
+ // Wrap in value holder because these values will not change anymore.
+ return PREFIX_JS+TPQFactory.ParameterValueFunction.CREATE_VALUE_HOLDER+"("+function+");";
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/AbstractTPQBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/AbstractTPQBuilder.java
new file mode 100644
index 0000000..c522c5d
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/AbstractTPQBuilder.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import java.util.function.Consumer;
+
+/**
+ * Abstract object builder with parent builder.
+ *
+ *
+ * @param
The parent builder.
+ * @param The object to build.
+ * @param This builder.
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public abstract class AbstractTPQBuilder
{
+
+ private final P parent;
+ private final T value;
+
+ /**
+ * Creates the builder.
+ * @param parent The parent builder.
+ * @param value The object to build.
+ */
+ public AbstractTPQBuilder(P parent,T value) {
+ this.parent=parent;
+ this.value=value;
+ }
+
+ protected P getParent() {
+ return parent;
+ }
+
+ protected T getValue() {
+ return value;
+ }
+
+ protected abstract B getBuilder();
+
+ /**
+ * Builds the result.
+ * @return The result.
+ */
+ public final P build() {
+ buildParent();
+ return getParent();
+ }
+
+ protected abstract void buildParent();
+
+ protected B make(Consumer mixer) {
+ mixer.accept(getValue());
+ return getBuilder();
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/AbstractTPQueryNodeBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/AbstractTPQueryNodeBuilder.java
new file mode 100644
index 0000000..7d4e364
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/AbstractTPQueryNodeBuilder.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import net.forwardfire.tpquery.model.AbstractTPQueryNode;
+import net.forwardfire.tpquery.model.TPQueryHint;
+
+/**
+ * Abstract query node builder for the shared properties of the AbstractTPQueryNode.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public abstract class AbstractTPQueryNodeBuilder
extends AbstractTPQBuilder
{
+
+ public AbstractTPQueryNodeBuilder(P parent, T build) {
+ super(parent, build);
+ }
+
+ /**
+ * Sets the language.
+ * @param language The langauge.
+ * @return The builder.
+ */
+ public B setLanguage(String language) {
+ return make(build -> build.setLanguage(language));
+ }
+
+ /**
+ * Sets the description.
+ * @param description The description.
+ * @return The builder;
+ */
+ public B setDescription(String description) {
+ return make(build -> build.setDescription(description));
+ }
+
+ /**
+ * Sets the template option.
+ * @param template The template option.
+ * @return The builder.
+ */
+ public B setTemplate(Boolean template) {
+ return make(build -> build.setTemplate(template));
+ }
+
+ /**
+ * Sets the timeout.
+ * @param timeout The timeout.
+ * @return The builder.
+ */
+ public B setTimeout(Integer timeout) {
+ return make(build -> build.setTimeout(timeout));
+ }
+
+ /**
+ * Adds an query hint.
+ * @param name The name.
+ * @param value The value.
+ * @return The builder.
+ */
+ public B addQueryHint(String name,String value) {
+ return make(build -> build.addQueryHint(new TPQueryHint(name,value)));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQConfigBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQConfigBuilder.java
new file mode 100644
index 0000000..efef2c5
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQConfigBuilder.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import javax.xml.bind.JAXBException;
+
+import net.forwardfire.tpquery.config.TPQConfig;
+import net.forwardfire.tpquery.model.TPQuerySet;
+import net.forwardfire.tpquery.model.TPQuerySetXMLMarshaller;
+import net.forwardfire.tpquery.statement.TPQStatementMarshaller;
+
+/**
+ * The root config builder.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 22, 2015
+ */
+public class TPQConfigBuilder {
+
+ private final TPQConfig storeConfig;
+ private final Supplier resultBuilder;
+ private final TPQuerySetXMLMarshaller xmlDriver;
+ private final TPQStatementMarshaller statementMarshaller;
+
+ /**
+ * Creates a config builder.
+ * @param storeConfig The config to build.
+ * @param resultBuilder the result of this builder.
+ * @throws JAXBException If the jaxb marshaller throws an error.
+ */
+ public TPQConfigBuilder(TPQConfig storeConfig,Supplier resultBuilder) throws JAXBException {
+ Objects.requireNonNull(storeConfig,"Can't build null config.");
+ Objects.requireNonNull(resultBuilder,"Can't build with null builder.");
+ this.storeConfig = storeConfig;
+ this.resultBuilder = resultBuilder;
+ this.xmlDriver = new TPQuerySetXMLMarshaller();
+ this.statementMarshaller = new TPQStatementMarshaller();
+ }
+
+ protected TPQStatementMarshaller getStatementMarshaller() {
+ return statementMarshaller;
+ }
+
+ /**
+ * Build the result.
+ * @return The result.
+ */
+ public T build() {
+ return resultBuilder.get();
+ }
+
+ /**
+ * Adds an query set.
+ * @param systemId The systemId of the query set.
+ * @param querySet The query set to add.
+ * @return The builder.
+ */
+ public TPQConfigBuilder addQuerySet(String systemId,TPQuerySet querySet) {
+ storeConfig.addQuerySet(systemId,querySet);
+ return this;
+ }
+
+ protected TPQConfigBuilder readQuerySet(InputStream input,String systemId) throws JAXBException {
+ Objects.requireNonNull(input, "Can't read null InputStream");
+ return addQuerySet(systemId,xmlDriver.unmarshal(input));
+ }
+
+ /**
+ * Reads an query set.
+ * @param resource The resource to read.
+ * @return The builder.
+ * @throws JAXBException When marshall error.
+ */
+ public TPQConfigBuilder readQuerySet(String resource) throws JAXBException {
+ Objects.requireNonNull(resource, "Can't read null resource");
+ return readQuerySet(getClass().getClassLoader().getResourceAsStream(resource),resource);
+ }
+
+ /**
+ * Reads an query set.
+ * @param file The file to read.
+ * @return The builder.
+ * @throws JAXBException When marshall error.
+ */
+ public TPQConfigBuilder readQuerySet(File file) throws JAXBException {
+ Objects.requireNonNull(file, "Can't read null File");
+ try {
+ return readQuerySet(new FileInputStream(file),file.getAbsolutePath());
+ } catch (FileNotFoundException e) {
+ throw new JAXBException(e);
+ }
+ }
+
+ /**
+ * Creates an query set.
+ * @param name The query set name.
+ * @param systemId The query set systemId.
+ * @return The builder.
+ */
+ public TPQuerySetBuilder createQuerySet(String name,String systemId) {
+ return new TPQuerySetBuilder(this,name,systemId);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryBuilder.java
new file mode 100644
index 0000000..7bf9489
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryBuilder.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.statement.TPQStatement;
+import net.forwardfire.tpquery.statement.TPQStatementPartInclude;
+import net.forwardfire.tpquery.statement.TPQStatementPartParameter;
+import net.forwardfire.tpquery.statement.TPQStatementPartText;
+
+/**
+ * Builds queries.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public class TPQueryBuilder extends AbstractTPQueryNodeBuilder
> {
+
+ private final TPQConfigBuilder configBuilder;
+ private final TPQueryBuilderParent builderParent;
+
+ /**
+ * Creates the query builder.
+ * @param configBuilder The parent config builder.
+ * @param parent The parent builder.
+ * @param name The name of the query.
+ * @param builderParent The callback to build the parent.
+ */
+ public TPQueryBuilder(TPQConfigBuilder configBuilder,P parent,String name,TPQueryBuilderParent builderParent) {
+ super(parent,new TPQuery(name));
+ this.configBuilder = configBuilder;
+ this.builderParent = builderParent;
+ }
+
+ @Override
+ protected TPQueryBuilder getBuilder() {
+ return this;
+ }
+
+ @Override
+ protected void buildParent() {
+ builderParent.buildChild(getValue());
+ }
+
+ // -------
+
+ /**
+ * Create a query parameter.
+ * @param name The parameter name.
+ * @param valueType The parameter value type.
+ * @return The builder.
+ */
+ public TPQueryParameterBuilder createQueryParameter(String name,String valueType) {
+ return new TPQueryParameterBuilder(this,name,valueType);
+ }
+
+ /**
+ * Create a query parameter.
+ * @param name The parameter name.
+ * @param valueTypeClass The parameter value type.
+ * @return The builder.
+ */
+ public TPQueryParameterBuilder createQueryParameter(String name,Class> valueTypeClass) {
+ Validate.notNull(valueTypeClass, "Can't append null valueTypeClass");
+ return createQueryParameter(name, valueTypeClass.getName());
+ }
+
+ /**
+ * Addes an query part.
+ * @param queryPart The part to add.
+ * @return The builder.
+ */
+ public TPQueryBuilder addQueryPart(TPQStatement queryPart) {
+ Validate.notNull(queryPart, "Can't append null queryPart");
+ getValue().addQueryPart(queryPart);
+ return this;
+ }
+
+ /**
+ * Parsed the statement into parts.
+ * @param value The statement value.
+ * @return The builder.
+ */
+ public TPQueryBuilder parseStatement(String value) {
+ Validate.notNull(value, "Can't parse null value");
+ getValue().getQueryParts().addAll(configBuilder.getStatementMarshaller().unmarshal(value));
+ return this;
+ }
+
+ /**
+ * Appends text part.
+ * @param value The part value.
+ * @return The builder.
+ */
+ public TPQueryBuilder appendText(String value) {
+ return addQueryPart(new TPQStatementPartText(Validate.notNull(value, "Can't append null textvalue")));
+ }
+
+ /**
+ * Appends parameter part.
+ * @param value The part value.
+ * @return The builder.
+ */
+ public TPQueryBuilder appendParameter(String value) {
+ return addQueryPart(new TPQStatementPartParameter(Validate.notNull(value, "Can't append null template value")));
+ }
+
+ /**
+ * Appends include part.
+ * @param value The part value.
+ * @return The builder.
+ */
+ public TPQueryBuilder appendInclude(String value) {
+ return addQueryPart(new TPQStatementPartInclude(Validate.notNull(value, "Can't append null include value")));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryBuilderParent.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryBuilderParent.java
new file mode 100644
index 0000000..bc6d977
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryBuilderParent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Build the parent for when we don't know the parent.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public interface TPQueryBuilderParent {
+
+ /**
+ * Build the query child to the parent.
+ * @param query The child query.
+ */
+ void buildChild(TPQuery query);
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryParameterBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryParameterBuilder.java
new file mode 100644
index 0000000..2645c8f
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQueryParameterBuilder.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQueryParameter;
+
+/**
+ * Builds query parameters.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public class TPQueryParameterBuilder extends AbstractTPQBuilder,TPQueryParameter,TPQueryParameterBuilder> {
+
+ public TPQueryParameterBuilder(TPQueryBuilder parent,String name,String valueType) {
+ super(parent,new TPQueryParameter(name,valueType));
+ }
+
+ @Override
+ protected TPQueryParameterBuilder getBuilder() {
+ return this;
+ }
+
+ @Override
+ protected void buildParent() {
+ getParent().getValue().addQueryParameter(getValue());
+ }
+
+ // -------
+
+ /**
+ * Sets the parameter type.
+ * @param type The type to set.
+ * @return The builder.
+ */
+ public TPQueryParameterBuilder setType(String type) {
+ return make(build -> build.setType(Validate.notNull(type, "Can't set null type")));
+ }
+
+ /**
+ * Sets the parameter default value.
+ * @param defaultValue The defaultValue to set.
+ * @return The builder.
+ */
+ public TPQueryParameterBuilder setDefaultValue(String defaultValue) {
+ return make(build -> build.setDefaultValue(Validate.notNull(defaultValue, "Can't set null default value")));
+ }
+
+ /**
+ * Sets the parameter nullable.
+ * @param nullable The nullable to set.
+ * @return The builder.
+ */
+ public TPQueryParameterBuilder setNullable(Boolean nullable) {
+ return make(build -> build.setNullable(Validate.notNull(nullable, "Can't set null nullable")));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQuerySetBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQuerySetBuilder.java
new file mode 100644
index 0000000..1c6c1a6
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQuerySetBuilder.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.model.TPQuerySet;
+
+/**
+ * Builds query set.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public class TPQuerySetBuilder extends AbstractTPQueryNodeBuilder,TPQuerySet,TPQuerySetBuilder> {
+
+ private final String systemId;
+
+ /**
+ * Creates an query set builder.
+ * @param parent The parent builder.
+ * @param name The name of the query set.
+ * @param systemId The systemId of the query set.
+ */
+ public TPQuerySetBuilder(TPQConfigBuilder parent,String name,String systemId) {
+ super(parent,new TPQuerySet(name));
+ this.systemId=systemId;
+ }
+
+ @Override
+ protected TPQuerySetBuilder getBuilder() {
+ return this;
+ }
+
+ @Override
+ protected void buildParent() {
+ getParent().addQuerySet(systemId, getValue());
+ }
+
+ // -------
+
+ /**
+ * Create a query.
+ * @param name The query name.
+ * @return The builder.
+ */
+ public TPQueryBuilder> createQuery(String name) {
+ return new TPQueryBuilder>(getParent(),this,name,new TPQueryBuilderParent() {
+ @Override
+ public void buildChild(TPQuery query) {
+ getValue().addQuery(query);
+ }
+ });
+ }
+
+ /**
+ * Adds a query set.
+ * @param qs The query set to add.
+ * @return The builder.
+ */
+ public TPQuerySetBuilder addQuerySet(TPQuerySet qs) {
+ return make(build -> build.addQuerySet(qs));
+ }
+
+ /**
+ * Create a query set tree.
+ * @param name The query set name.
+ * @return The tree builder.
+ */
+ public TPQuerySetNodeBuilder createQuerySetTree(String name) {
+ return new TPQuerySetNodeBuilder(this,null,name);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQuerySetNodeBuilder.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQuerySetNodeBuilder.java
new file mode 100644
index 0000000..139bc18
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/TPQuerySetNodeBuilder.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.builder;
+
+import java.util.Objects;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.model.TPQuerySet;
+
+/**
+ * Builds query set as tree.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 29, 2015
+ */
+public class TPQuerySetNodeBuilder extends AbstractTPQueryNodeBuilder,TPQuerySet,TPQuerySetNodeBuilder> {
+
+ private final TPQuerySetBuilder treeRoot;
+
+ /**
+ * Creates an query set node.
+ * @param treeRoot The root query set builder.
+ * @param parent The parent builder.
+ * @param name The query set name.
+ */
+ public TPQuerySetNodeBuilder(TPQuerySetBuilder treeRoot,TPQuerySetNodeBuilder parent,String name) {
+ super(parent,new TPQuerySet(name));
+ this.treeRoot=treeRoot;
+ }
+
+ @Override
+ protected TPQuerySetNodeBuilder getBuilder() {
+ return this;
+ }
+
+ @Override
+ protected void buildParent() {
+ Validate.validState(Objects.nonNull(getParent()),"build() on root node is illegal use buildTree()");
+ getParent().addQuerySet(getValue());
+ }
+
+ /**
+ * Builds the tree and returns the parent query set builder.
+ * @return The builder.
+ */
+ public TPQuerySetBuilder buildTree() {
+ Validate.validState(Objects.isNull(getParent()),"buildTree() only works on tree root node.");
+ treeRoot.addQuerySet(getValue());
+ return treeRoot;
+ }
+
+ // -------
+
+ /**
+ * Create a query.
+ * @param name The query name.
+ * @return The builder.
+ */
+ public TPQueryBuilder> createQuery(String name) {
+ return new TPQueryBuilder>(treeRoot.getParent(),this,name,new TPQueryBuilderParent() {
+ @Override
+ public void buildChild(TPQuery query) {
+ getValue().addQuery(query);
+ }
+ });
+ }
+
+ /**
+ * Adds a query set.
+ * @param qs The query set to add.
+ * @return The builder.
+ */
+ public TPQuerySetNodeBuilder addQuerySet(TPQuerySet qs) {
+ return make(build -> build.addQuerySet(qs));
+ }
+
+ /**
+ * Create a query set.
+ * @param name The query set name.
+ * @return The builder.
+ */
+ public TPQuerySetNodeBuilder createQuerySet(String name) {
+ return new TPQuerySetNodeBuilder(treeRoot,this,name);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/package-info.java
new file mode 100644
index 0000000..2d94af6
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/builder/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Builders for query-sets and queries.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.config.builder;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/package-info.java
new file mode 100644
index 0000000..6dedf7e
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Config of the queries and languages,types,etc.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.config;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/AbstractTPQConfigValidatorParameterPattern.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/AbstractTPQConfigValidatorParameterPattern.java
new file mode 100644
index 0000000..806c61e
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/AbstractTPQConfigValidatorParameterPattern.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+import java.util.function.Function;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.model.TPQueryParameter;
+
+/**
+ * Abstract pattern checker which used an Function to get the value to check the pattern against.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public abstract class AbstractTPQConfigValidatorParameterPattern implements TPQConfigValidatorCheck {
+
+ private final String pattern;
+ private final Function patternValue;
+
+ /**
+ * Creates this pattern check.
+ * @param pattern The pattern to check.
+ * @param patternValue The function to get value to check.
+ */
+ public AbstractTPQConfigValidatorParameterPattern(String pattern,Function patternValue) {
+ Validate.notNull(patternValue);
+ this.pattern=pattern;
+ this.patternValue=patternValue;
+ }
+
+ @Override
+ public void validateQuery(TPQuery query) {
+ query.getQueryParameters().forEach(p -> {
+ String value = patternValue.apply(p);
+ Validate.notNull(value,"%s need non null value",this.getClass().getName());
+ Validate.matchesPattern(value, pattern, "validation failed on query %s, parameter: %s value: %s does not match %s",query.getName(),p.getName(),value,pattern);
+ });
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidator.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidator.java
new file mode 100644
index 0000000..1904642
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidator.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+import org.apache.commons.lang3.Validate;
+
+/**
+ * Holds the query name pattern fot he config validator checker.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public class TPQConfigValidator {
+
+ private final String pattern;
+ private final TPQConfigValidatorCheck check;
+
+ /**
+ * Creates an config validator.
+ * @param pattern The query name pattern.
+ * @param check The checker to validate the queries which match the pattern.
+ */
+ public TPQConfigValidator(String pattern, TPQConfigValidatorCheck check) {
+ Validate.notBlank(pattern);
+ Validate.notNull(check);
+ this.pattern = pattern;
+ this.check = check;
+ }
+
+ /**
+ * @return the pattern
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ /**
+ * @return the check
+ */
+ public TPQConfigValidatorCheck getCheck() {
+ return check;
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheck.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheck.java
new file mode 100644
index 0000000..67ec208
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheck.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * validates the given query.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 17, 2015
+ */
+public interface TPQConfigValidatorCheck {
+
+ /**
+ * Validate this query.
+ * @param query The query to validate.
+ */
+ void validateQuery(TPQuery query);
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckDescriptionNotBlank.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckDescriptionNotBlank.java
new file mode 100644
index 0000000..9f8d61b
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckDescriptionNotBlank.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Checks the query description to a pattern.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public final class TPQConfigValidatorCheckDescriptionNotBlank implements TPQConfigValidatorCheck {
+
+ @Override
+ public void validateQuery(TPQuery query) {
+ Validate.notBlank(query.getDescription());
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckNamePattern.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckNamePattern.java
new file mode 100644
index 0000000..df0640b
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckNamePattern.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Checks the query name to a pattern.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public final class TPQConfigValidatorCheckNamePattern implements TPQConfigValidatorCheck {
+
+ private final String pattern;
+
+ public TPQConfigValidatorCheckNamePattern(String pattern) {
+ Validate.matchesPattern("", pattern);
+ this.pattern=pattern;
+ }
+
+ @Override
+ public void validateQuery(TPQuery query) {
+ Validate.matchesPattern(query.getName(), pattern);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterDefaultValueNotBlank.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterDefaultValueNotBlank.java
new file mode 100644
index 0000000..fe2cf7c
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterDefaultValueNotBlank.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Checks the query parameters default value to a pattern.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public final class TPQConfigValidatorCheckParameterDefaultValueNotBlank implements TPQConfigValidatorCheck {
+
+ @Override
+ public void validateQuery(TPQuery query) {
+ query.getQueryParameters().forEach(p -> Validate.notBlank(p.getDefaultValue()));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterNamePattern.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterNamePattern.java
new file mode 100644
index 0000000..fab1a1c
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterNamePattern.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+/**
+ * Checks the query parameters name to a pattern.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public final class TPQConfigValidatorCheckParameterNamePattern extends AbstractTPQConfigValidatorParameterPattern {
+
+ public TPQConfigValidatorCheckParameterNamePattern(String pattern) {
+ super(pattern,p -> p.getName());
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterTypePattern.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterTypePattern.java
new file mode 100644
index 0000000..5fa8d9a
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterTypePattern.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+/**
+ * Checks the query parameters type to a pattern.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public final class TPQConfigValidatorCheckParameterTypePattern extends AbstractTPQConfigValidatorParameterPattern {
+
+ public TPQConfigValidatorCheckParameterTypePattern(String pattern) {
+ super(pattern,p -> p.getType());
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterValueTypePattern.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterValueTypePattern.java
new file mode 100644
index 0000000..f709478
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/TPQConfigValidatorCheckParameterValueTypePattern.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.config.validate;
+
+/**
+ * Checks the query parameters value type to a pattern.
+ *
+ * @author Willem Cazander
+ * @version 1.0 June 1, 2015
+ */
+public final class TPQConfigValidatorCheckParameterValueTypePattern extends AbstractTPQConfigValidatorParameterPattern {
+
+ public TPQConfigValidatorCheckParameterValueTypePattern(String pattern) {
+ super(pattern,p -> p.getValueType());
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/package-info.java
new file mode 100644
index 0000000..80a5826
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/config/validate/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Extra query model validation checks.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.config.validate;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/AbstractTPQueryNode.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/AbstractTPQueryNode.java
new file mode 100644
index 0000000..6dc0778
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/AbstractTPQueryNode.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+import net.forwardfire.tpquery.model.AbstractXMLMarshaller.Attribute;
+import net.forwardfire.tpquery.model.AbstractXMLMarshaller.Element;
+
+/**
+ * AbstractTPQueryNode has the shared properties of an query(set) node.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 18, 2015
+ */
+public abstract class AbstractTPQueryNode {
+
+ private String name = null;
+ private String description = null;
+ private String language = null;
+ private Boolean template = null;
+ private Integer timeout = null;
+ private final List queryHints;
+
+ public AbstractTPQueryNode() {
+ queryHints = new ArrayList<>();
+ }
+
+ /**
+ * @return the name
+ */
+ @XmlAttribute(name=Attribute.NAME,required=AbstractXMLMarshaller.Meta.REQUIRED)
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the description
+ */
+ @XmlElement(name=Element.QUERY_DESCRIPTION)
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * @return the language
+ */
+ @XmlAttribute(name=Attribute.LANGUAGE)
+ public String getLanguage() {
+ return language;
+ }
+
+ /**
+ * @param language the language to set
+ */
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ /**
+ * @return the template
+ */
+ @XmlAttribute(name=Attribute.TEMPLATE)
+ public Boolean getTemplate() {
+ return template;
+ }
+
+ /**
+ * @param template the template to set
+ */
+ public void setTemplate(Boolean template) {
+ this.template = template;
+ }
+
+ /**
+ * @return the timeout
+ */
+ @XmlAttribute(name=Attribute.TIMEOUT)
+ public Integer getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * @param timeout the timeout to set
+ */
+ public void setTimeout(Integer timeout) {
+ this.timeout = timeout;
+ }
+
+ /**
+ * @return the queryHints
+ */
+ @XmlElement(name=Element.QUERY_HINT)
+ public List getQueryHints() {
+ return queryHints;
+ }
+
+ /**
+ * @param queryHint the queryHint to add
+ */
+ public void addQueryHint(TPQueryHint queryHint) {
+ Objects.requireNonNull(queryHint);
+ queryHints.add(queryHint);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/AbstractXMLMarshaller.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/AbstractXMLMarshaller.java
new file mode 100644
index 0000000..1d55b90
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/AbstractXMLMarshaller.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+/**
+ * AbstractXMLMarshaller has all jaxb meta info.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 16, 2015
+ */
+abstract class AbstractXMLMarshaller {
+
+ protected static final String XML_ENCODING = "UTF-8";
+
+ protected AbstractXMLMarshaller() {
+ }
+
+ protected static class Meta {
+ protected static final boolean REQUIRED = true;
+ protected Meta() {
+ }
+ }
+
+ protected static class Element {
+ protected static final String QUERY_SET = "query-set";
+ protected static final String QUERY = "query";
+ protected static final String QUERY_DESCRIPTION = "description";
+ protected static final String QUERY_HINT = "hint";
+ protected static final String QUERY_PARAMETER = "parameter";
+ protected static final String QUERY_PART = "statement";
+ protected Element() {
+ }
+ }
+
+ protected static class Attribute {
+ protected static final String NAME = "name";
+ protected static final String VALUE = "value";
+ protected static final String TYPE = "type";
+ protected static final String DEFAULT_VALUE = "defaultValue";
+ protected static final String TIMEOUT = "timeout";
+ protected static final String TEMPLATE = "template";
+ protected static final String LANGUAGE = "language";
+ protected static final String VALUE_TYPE = "valueType";
+ protected static final String NULLABLE = "nullable";
+ protected Attribute() {
+ }
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuery.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuery.java
new file mode 100644
index 0000000..540c148
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuery.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import net.forwardfire.tpquery.model.AbstractXMLMarshaller.Element;
+import net.forwardfire.tpquery.statement.TPQStatement;
+import net.forwardfire.tpquery.statement.TPQStatementMarshallerAdapter;
+
+/**
+ * Defines a query.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+public final class TPQuery extends AbstractTPQueryNode {
+
+ private List queryParts;
+ private final List queryParameters;
+
+ public TPQuery() {
+ queryParts = new ArrayList<>();
+ queryParameters = new ArrayList<>();
+ }
+
+ public TPQuery(String name) {
+ this();
+ setName(name);
+ }
+
+ /**
+ * @return the queryParts
+ */
+ @XmlElement(name=Element.QUERY_PART,required=AbstractXMLMarshaller.Meta.REQUIRED)
+ @XmlJavaTypeAdapter(TPQStatementMarshallerAdapter.class)
+ public List getQueryParts() {
+ return queryParts;
+ }
+
+ public void setQueryParts(List parts) {
+ Objects.requireNonNull(parts,"Can't set null list");
+ queryParts = parts;
+ }
+
+ public void addQueryPart(TPQStatement queryPart) {
+ Objects.requireNonNull(queryPart,"Can't add null");
+ queryParts.add(queryPart);
+ }
+
+ /**
+ * @return the queryParameters
+ */
+ @XmlElement(name=Element.QUERY_PARAMETER)
+ public List getQueryParameters() {
+ return queryParameters;
+ }
+
+ public void addQueryParameter(TPQueryParameter queryParameter) {
+ Objects.requireNonNull(queryParameter,"Can't add null");
+ Objects.requireNonNull(queryParameter.getName(),"TQueryParameter.getName() is null.");
+ queryParameters.add(queryParameter);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQueryHint.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQueryHint.java
new file mode 100644
index 0000000..cda1aa1
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQueryHint.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+import net.forwardfire.tpquery.model.AbstractXMLMarshaller.Attribute;
+
+/**
+ * Query hint are optional hint.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+public final class TPQueryHint {
+
+ private String name = null;
+ private String value = null;
+
+ public TPQueryHint() {
+ }
+
+ public TPQueryHint(String name) {
+ this();
+ setName(name);
+ }
+
+ public TPQueryHint(String name,String value) {
+ this(name);
+ setValue(value);
+ }
+
+ /**
+ * @return the name
+ */
+ @XmlAttribute(name=Attribute.NAME,required=AbstractXMLMarshaller.Meta.REQUIRED)
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the value
+ */
+ @XmlAttribute(name=Attribute.VALUE,required=AbstractXMLMarshaller.Meta.REQUIRED)
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * @param value the value to set
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQueryParameter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQueryParameter.java
new file mode 100644
index 0000000..6843e6a
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQueryParameter.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+import net.forwardfire.tpquery.model.AbstractXMLMarshaller.Attribute;
+
+/**
+ * Defines the query parameter.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+public final class TPQueryParameter {
+
+ private String name = null;
+ private String defaultValue = null;
+ private String type = null;
+ private String valueType = null;
+ private Boolean nullable = null;
+
+ public TPQueryParameter() {
+ }
+
+ public TPQueryParameter(String name,String valueType) {
+ setName(name);
+ setValueType(valueType);
+ }
+
+ /**
+ * @return the name
+ */
+ @XmlAttribute(name=Attribute.NAME,required=AbstractXMLMarshaller.Meta.REQUIRED)
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the defaultValue
+ */
+ @XmlAttribute(name=Attribute.DEFAULT_VALUE)
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * @param defaultValue the defaultValue to set
+ */
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * @return the type
+ */
+ @XmlAttribute(name=Attribute.TYPE)
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * @return the valueType
+ */
+ @XmlAttribute(name=Attribute.VALUE_TYPE,required=AbstractXMLMarshaller.Meta.REQUIRED)
+ public String getValueType() {
+ return valueType;
+ }
+
+ /**
+ * @param valueType the valueType to set
+ */
+ public void setValueType(String valueType) {
+ this.valueType = valueType;
+ }
+
+ /**
+ * @return the nullable
+ */
+ @XmlAttribute(name=Attribute.NULLABLE)
+ public Boolean getNullable() {
+ return nullable;
+ }
+
+ /**
+ * @param nullable the nullable to set
+ */
+ public void setNullable(Boolean nullable) {
+ this.nullable = nullable;
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuerySet.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuerySet.java
new file mode 100644
index 0000000..ee457c2
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuerySet.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import net.forwardfire.tpquery.model.AbstractXMLMarshaller.Element;
+
+/**
+ * Query sets is an tree node which holds more query sets and queries.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+@XmlRootElement(name=Element.QUERY_SET)
+public class TPQuerySet extends AbstractTPQueryNode {
+
+ private final List querySets;
+ private final List queries;
+
+ public TPQuerySet() {
+ queries = new ArrayList<>();
+ querySets = new ArrayList<>();
+ }
+
+ public TPQuerySet(String name) {
+ this();
+ setName(name);
+ }
+
+ /**
+ * @return the queries
+ */
+ @XmlElement(name=Element.QUERY)
+ public List getQueries() {
+ return queries;
+ }
+
+ /**
+ * @param query the query to add
+ */
+ public void addQuery(TPQuery query) {
+ queries.add(query);
+ }
+
+ /**
+ * @return the querySets
+ */
+ @XmlElement(name=Element.QUERY_SET)
+ public List getQuerySets() {
+ return querySets;
+ }
+
+ /**
+ * @param querySet the querySet to add
+ */
+ public void addQuerySet(TPQuerySet querySet) {
+ querySets.add(querySet);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuerySetXMLMarshaller.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuerySetXMLMarshaller.java
new file mode 100644
index 0000000..77d58b9
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/TPQuerySetXMLMarshaller.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.model;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Objects;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+/**
+ * Jaxb marshaller of the query sets.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+public class TPQuerySetXMLMarshaller extends AbstractXMLMarshaller {
+
+ private final JAXBContext querySetContext;
+
+ public TPQuerySetXMLMarshaller() throws JAXBException {
+ this(JAXBContext.newInstance(TPQuerySet.class));
+ }
+
+ public TPQuerySetXMLMarshaller(JAXBContext querySetContext) {
+ Objects.requireNonNull(querySetContext,"querySetContext is null.");
+ this.querySetContext = querySetContext;
+ }
+
+ public void marshal(TPQuerySet querySet, OutputStream output) throws JAXBException {
+ Objects.requireNonNull(querySet,"querySet is null.");
+ Objects.requireNonNull(output,"OutputStream is null.");
+
+ Marshaller marshaller = querySetContext.createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ marshaller.setProperty(Marshaller.JAXB_ENCODING, XML_ENCODING);
+ marshaller.marshal(querySet, output);
+ }
+
+ public TPQuerySet unmarshal(InputStream input) throws JAXBException {
+ Objects.requireNonNull(input,"InputStream is null.");
+
+ Unmarshaller unmarshaller = querySetContext.createUnmarshaller();
+ return (TPQuerySet) unmarshaller.unmarshal(input);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/model/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/package-info.java
new file mode 100644
index 0000000..f4a11c0
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/model/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * The query data model.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.model;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/package-info.java
new file mode 100644
index 0000000..7d5153b
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Templated Prepared Query manager and factory.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/AbstractTPQStatement.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/AbstractTPQStatement.java
new file mode 100644
index 0000000..465b339
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/AbstractTPQStatement.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Abstract implementation of a statement.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 21, 2015
+ */
+public abstract class AbstractTPQStatement implements TPQStatement {
+
+ private final String statementPart;
+ private TPQStatementContext context;
+ private TPQuery query;
+
+ public AbstractTPQStatement(String statementPart) {
+ Validate.notNull(statementPart,"statementPart is null");
+ this.statementPart=statementPart;
+ }
+
+ @Override
+ public final void prepareInit(TPQStatementContext context, TPQuery query) {
+ this.context=context;
+ this.query=query;
+ prepareInit();
+ }
+
+ protected void prepareInit() {
+ }
+
+ @Override
+ public final String getStatementPart() {
+ return statementPart;
+ }
+
+ /**
+ * @return the context
+ */
+ public final TPQStatementContext getContext() {
+ return context;
+ }
+
+ /**
+ * @return the query
+ */
+ public final TPQuery getQuery() {
+ return query;
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/AbstractTPQStatementWriter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/AbstractTPQStatementWriter.java
new file mode 100644
index 0000000..645adc0
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/AbstractTPQStatementWriter.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.model.TPQueryParameter;
+import net.forwardfire.tpquery.store.TPQueryStoreStatementMapper;
+
+/**
+ * Abstract implementation of the statement writer.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 20, 2015
+ */
+public abstract class AbstractTPQStatementWriter implements TPQStatementWriter {
+
+ protected static final String PARAMETER_PREPARED = "?";
+ protected static final String PARAMETER_NEXT = ",";
+ private static final int OUTPUT_START_SIZE = 384;
+
+ protected boolean flagValueBased = false;
+ protected final StringBuilder output;
+ protected final List queryParameterMapping;
+ protected final Map queryParameterData;
+
+ public AbstractTPQStatementWriter(Map queryParameterData) {
+ Validate.notNull(queryParameterData);
+ this.queryParameterData=queryParameterData;
+ this.output = new StringBuilder(OUTPUT_START_SIZE);
+ this.queryParameterMapping = new ArrayList<>();
+ }
+
+ @Override
+ public void writeQuery(TPQuery query) {
+ Validate.notNull(query,"Can' write null query ");
+ query.getQueryParts().forEach(part -> part.prepare(this));
+ }
+
+ @Override
+ public Object getParameterValue(TPQueryParameter parameter) {
+ return queryParameterData.get(parameter.getName());
+ }
+
+ @Override
+ public boolean isValueMappedWriter() {
+ return true;
+ }
+
+ @Override
+ public void appendQueryText(String text) {
+ Validate.notNull(text, "Can't add null text.");
+ output.append(text);
+ }
+
+ @Override
+ public void appendQueryParameter(TPQueryStoreStatementMapper mapper) {
+ Validate.notNull(mapper);
+ queryParameterMapping.add(mapper);
+ output.append(PARAMETER_PREPARED);
+ }
+
+ @Override
+ public void appendQueryParameterSeperator() {
+ output.append(PARAMETER_NEXT);
+ }
+
+ @Override
+ public List getQueryParameterMapping() {
+ return queryParameterMapping;
+ }
+
+ @Override
+ public String getQueryText() {
+ return output.toString();
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatement.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatement.java
new file mode 100644
index 0000000..37ae47b
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatement.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Defines an query statement part.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 14, 2015
+ */
+public interface TPQStatement {
+
+ /**
+ * Init the query.
+ * @param context The prepare context.
+ * @param query The query to prepare.
+ */
+ void prepareInit(TPQStatementContext context,TPQuery query);
+
+ /**
+ * Writers all prepares statement parts to the query writer.
+ * @param queryWriter The query writer to build the prepared query with.
+ */
+ void prepare(TPQStatementWriter queryWriter);
+
+ /**
+ * @return the value of the statement part.
+ */
+ String getStatementPart();
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementContext.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementContext.java
new file mode 100644
index 0000000..84004a0
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementContext.java
@@ -0,0 +1,78 @@
+/*
+
+
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import java.util.Map;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.model.TPQueryParameter;
+import net.forwardfire.tpquery.statement.language.TPQStatementLanguage;
+import net.forwardfire.tpquery.statement.parameter.TPQStatementParameter;
+
+/**
+ * Gives statement parts the needed references to data.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 14, 2015
+ */
+public interface TPQStatementContext {
+
+ /**
+ * Get a query by name.
+ * @param name The name of the query.
+ * @return The query.
+ */
+ TPQuery getQuery(String name);
+
+ /**
+ * Returns a statement type based on the parameter.
+ * @param param The parameter to get the statement parameter type for.
+ * @return The statement parameter.
+ */
+ TPQStatementParameter getParameterType(TPQueryParameter param);
+
+ /**
+ * Returns a statement language based on the query.
+ * @param query The query to get the statement language for.
+ * @return The statement language.
+ */
+ TPQStatementLanguage getStatementLanguage(TPQuery query);
+
+ /**
+ * Gets a query parameter by name.
+ * note: may move back to TPQuery
+ *
+ * @param query The query having the parameter.
+ * @param name The name of the paramter.
+ * @return The query parameter.
+ */
+ TPQueryParameter getQueryParameterByName(TPQuery query,String name);
+
+ /**
+ * Retuns an map to store context in while writing an prepared statement.
+ * @return The context map.
+ */
+ Map getContextState();
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementMarshaller.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementMarshaller.java
new file mode 100644
index 0000000..f67281a
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementMarshaller.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.commons.lang3.Validate;
+
+/**
+ * Prints and parse the different statement parts.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 22, 2015
+ */
+public class TPQStatementMarshaller {
+
+ protected static final String DELIMITER = "$$";
+ protected static final String INCLUDE_PREFIX = "inc:";
+ private static final int DEFAULT_PRINT_SIZE = 384;
+
+ public String marshal(List parts) {
+ Objects.requireNonNull(parts,"Can't print null list.");
+ StringBuilder buf = new StringBuilder(DEFAULT_PRINT_SIZE);
+ for (TPQStatement part : parts) {
+ if (part instanceof TPQStatementPartParameter) {
+ buf.append(DELIMITER);
+ buf.append(part.getStatementPart());
+ buf.append(DELIMITER);
+ } else if (part instanceof TPQStatementPartInclude) {
+ buf.append(DELIMITER);
+ buf.append(INCLUDE_PREFIX);
+ buf.append(part.getStatementPart());
+ buf.append(DELIMITER);
+ } else {
+ buf.append(part.getStatementPart());
+ }
+ }
+ return buf.toString();
+ }
+
+ public List unmarshal(String statementTemplateText) {
+ Objects.requireNonNull(statementTemplateText,"Can't parse null text.");
+ List result = new ArrayList<>();
+ parseLoop(result,statementTemplateText);
+ return result;
+ }
+
+ private void appendText(List result,String text) {
+ if (text.isEmpty()) {
+ return;
+ }
+ result.add(new TPQStatementPartText(text));
+ }
+
+ private void parseLoop(List result,String value) {
+
+ // search for start delimiter
+ int searchIndex = value.indexOf(DELIMITER);
+ if (searchIndex < 0) {
+ appendText(result,value);
+ return; // only text
+ }
+
+ // search for end delimiter
+ int searchIndexEnd = value.indexOf(DELIMITER, searchIndex + DELIMITER.length());
+ Validate.isTrue(searchIndexEnd > 0, "Can't parse token without end delimiter: %s",DELIMITER);
+
+ // Split the template
+ String pre = value.substring(0,searchIndex);
+ String token = value.substring(searchIndex + DELIMITER.length(),searchIndexEnd);
+ String next = value.substring(searchIndexEnd + DELIMITER.length());
+
+ // Handle split results.
+ appendText(result,pre);
+ parseToken(result,token);
+ parseLoop(result,next);
+ }
+
+ private void parseToken(List result,String token) {
+ Validate.notEmpty(token,"Can't parse empty token.");
+ if (token.startsWith(INCLUDE_PREFIX)) {
+ result.add(new TPQStatementPartInclude(token.substring(INCLUDE_PREFIX.length())));
+ } else {
+ result.add(new TPQStatementPartParameter(token));
+ }
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementMarshallerAdapter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementMarshallerAdapter.java
new file mode 100644
index 0000000..a32f16d
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementMarshallerAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * jaxb adapter to marshall the statement parts.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 15, 2015
+ */
+public class TPQStatementMarshallerAdapter extends XmlAdapter> {
+
+ protected final TPQStatementMarshaller statementMarshaller = new TPQStatementMarshaller();
+
+ @Override
+ public String marshal(List parts) throws Exception {
+ return statementMarshaller.marshal(ObjectUtils.defaultIfNull(parts, new ArrayList()));
+ }
+
+ @Override
+ public List unmarshal(String value) throws Exception {
+ return statementMarshaller.unmarshal(StringUtils.defaultString(value));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartInclude.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartInclude.java
new file mode 100644
index 0000000..003d411
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartInclude.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import java.util.Objects;
+
+import org.apache.commons.lang3.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.forwardfire.tpquery.model.TPQuery;
+
+/**
+ * Handles query include statement parts.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 16, 2015
+ */
+public class TPQStatementPartInclude extends AbstractTPQStatement {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TPQStatementPartInclude.class);
+ private TPQuery includeQuery;
+
+ /**
+ * Creates an query include part.
+ * @param value The part value.
+ */
+ public TPQStatementPartInclude(String value) {
+ super(value);
+ LOG.trace(" include part created {}",value);
+ }
+
+ @Override
+ public void prepareInit() {
+ String key = getQuery().getName();
+ LOG.trace("init add loop lock: {}",key);
+ Validate.isTrue(Objects.isNull(getContext().getContextState().get(key)), "Duplicate treeLock key: %s", key);
+ getContext().getContextState().put(key,getClass().getName());
+
+ LOG.trace("init lookup query: {}",getStatementPart());
+ includeQuery = getContext().getQuery(getStatementPart());
+ Validate.isTrue(includeQuery.getTemplate(), "query: %s is not a template.", includeQuery.getName());
+
+ LOG.trace("init prepare included query."); // so all parameters are copies down the tree.
+ includeQuery.getQueryParts().forEach(part -> part.prepareInit(getContext(), includeQuery));
+
+ LOG.debug("init copy parameters: {} to: {}",includeQuery.getQueryParameters().size(),getQuery().getQueryParameters().size());
+ getQuery().getQueryParameters().addAll(includeQuery.getQueryParameters());
+
+ LOG.trace("init remove loop lock: {}",key);
+ getContext().getContextState().remove(key);
+ }
+
+ @Override
+ public void prepare(TPQStatementWriter queryWriter) {
+ queryWriter.writeQuery(includeQuery);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartParameter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartParameter.java
new file mode 100644
index 0000000..3455f47
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartParameter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import net.forwardfire.tpquery.model.TPQueryParameter;
+
+/**
+ * Handles parameter statement parts.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 16, 2015
+ */
+public class TPQStatementPartParameter extends AbstractTPQStatement {
+
+ private TPQueryParameter parameter;
+
+ /**
+ * Creates parameter statement part.
+ * @param value The part value.
+ */
+ public TPQStatementPartParameter(String value) {
+ super(value);
+ }
+
+ @Override
+ public void prepareInit() {
+ parameter = getContext().getQueryParameterByName(getQuery(),getStatementPart());
+ }
+
+ @Override
+ public void prepare(TPQStatementWriter queryWriter) {
+ getContext().getParameterType(parameter).prepareParameter(queryWriter, parameter, queryWriter.getParameterValue(parameter));
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartText.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartText.java
new file mode 100644
index 0000000..af7e09c
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementPartText.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+/**
+ * Handles query text statement parts.
+ *
+ * @author Willem Cazander
+ * @version 1.0 Jan 15, 2015
+ */
+public class TPQStatementPartText extends AbstractTPQStatement {
+
+ public TPQStatementPartText(String statementPart) {
+ super(statementPart);
+ }
+
+ @Override
+ public void prepare(TPQStatementWriter queryWriter) {
+ queryWriter.appendQueryText(getStatementPart());
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementWriter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementWriter.java
new file mode 100644
index 0000000..8507840
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/TPQStatementWriter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement;
+
+import java.util.List;
+
+import net.forwardfire.tpquery.model.TPQuery;
+import net.forwardfire.tpquery.model.TPQueryParameter;
+import net.forwardfire.tpquery.store.TPQueryStoreStatementMapper;
+
+/**
+ * Writes the statement query as text, and holds the parameter mapping for it.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 17, 2015
+ */
+public interface TPQStatementWriter {
+
+ /**
+ * Write all query parts.
+ * @param query The query to write.
+ */
+ void writeQuery(TPQuery query);
+
+
+ Object getParameterValue(TPQueryParameter parameter);
+
+ /**
+ * Defines if this writer supports the statement value mapper.
+ * @return false if the mapper are used directly by this writer.
+ */
+ boolean isValueMappedWriter();
+
+ /**
+ * Append query text to the statement.
+ * @param text The query part text to add.
+ */
+ void appendQueryText(String text);
+
+ void appendQueryParameter(TPQueryStoreStatementMapper valueMapper);
+
+ void appendQueryParameterSeperator();
+
+ /**
+ * @return The parameter mapping for the writen query.
+ */
+ List getQueryParameterMapping();
+
+ /**
+ * The statement query text.
+ * @return The statement query text.
+ */
+ String getQueryText();
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/AbstractTPQStatementLanguage.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/AbstractTPQStatementLanguage.java
new file mode 100644
index 0000000..2295dfb
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/AbstractTPQStatementLanguage.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.language;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.statement.AbstractTPQStatementWriter;
+import net.forwardfire.tpquery.statement.TPQStatementWriter;
+
+/**
+ * AbstractTQueryLanguageType holds the languageType key value and implements some default methods.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 22, 2015
+ */
+public abstract class AbstractTPQStatementLanguage implements TPQStatementLanguage {
+
+ private final String languageType;
+
+ /**
+ * Creates the abstract language type.
+ * @param languageType The languageType key.
+ */
+ public AbstractTPQStatementLanguage(String languageType) {
+ Validate.notNull(languageType, "languageType is null.");
+ this.languageType=languageType;
+ }
+
+ @Override
+ public final String getLanguageType() {
+ return languageType;
+ }
+
+ @Override
+ public TPQStatementWriter createQueryWriter(Map parameterData) {
+ return new TQueryStatementWriterPrepared(parameterData);
+ }
+
+ private class TQueryStatementWriterPrepared extends AbstractTPQStatementWriter {
+ private TQueryStatementWriterPrepared(Map queryParameterData) {
+ super(queryParameterData);
+ }
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguage.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguage.java
new file mode 100644
index 0000000..34c9cb8
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguage.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.language;
+
+import java.util.Map;
+
+import net.forwardfire.tpquery.statement.TPQStatementWriter;
+
+/**
+ * Allows for different language writers to define how the query is writen as statement text.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 18, 2015
+ */
+public interface TPQStatementLanguage {
+
+ /**
+ * The language type.
+ * @return The type of language.
+ */
+ String getLanguageType();
+
+ /**
+ * Creates a statement writer for this language.
+ * @param parameterData The request parameter data.
+ * @return The writer for this data.
+ */
+ TPQStatementWriter createQueryWriter(Map parameterData);
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguageHql.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguageHql.java
new file mode 100644
index 0000000..69a40ad
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguageHql.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.language;
+
+import java.util.Map;
+
+import net.forwardfire.tpquery.statement.AbstractTPQStatementWriter;
+import net.forwardfire.tpquery.statement.TPQStatementWriter;
+import net.forwardfire.tpquery.store.TPQueryStoreStatementMapper;
+
+/**
+ * Writes parameters as jpa ordered query syntax.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 18, 2015
+ */
+public class TPQStatementLanguageHql extends AbstractTPQStatementLanguage {
+
+ /**
+ * Creates the hql language type.
+ * @param languageType The languageType key.
+ */
+ public TPQStatementLanguageHql(String languageType) {
+ super(languageType);
+ }
+
+ @Override
+ public TPQStatementWriter createQueryWriter(Map parameterData) {
+ return new TQueryStatementWriterPreparedHql(parameterData);
+ }
+
+ private class TQueryStatementWriterPreparedHql extends AbstractTPQStatementWriter {
+ private TQueryStatementWriterPreparedHql(Map queryParameterData) {
+ super(queryParameterData);
+ }
+ @Override
+ public void appendQueryParameter(TPQueryStoreStatementMapper valueMapper) {
+ super.appendQueryParameter(valueMapper);
+ output.append(this.queryParameterMapping.size());
+ }
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguageSql.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguageSql.java
new file mode 100644
index 0000000..fcefeaf
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/TPQStatementLanguageSql.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.language;
+
+/**
+ * Writes parameters as jdbc prepared statement syntax.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 18, 2015
+ */
+public class TPQStatementLanguageSql extends AbstractTPQStatementLanguage {
+
+ /**
+ * Creates the sql language type.
+ * @param languageType The languageType key.
+ */
+ public TPQStatementLanguageSql(String languageType) {
+ super(languageType);
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/package-info.java
new file mode 100644
index 0000000..57ee680
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/language/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Writer support for different parameterized query languages.
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.statement.language;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/package-info.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/package-info.java
new file mode 100644
index 0000000..1b44a56
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Query statements are written from parts: TEXT,PARAMETER,INCLUDE
+ *
+ * @author Willem Cazander
+ */
+package net.forwardfire.tpquery.statement;
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/AbstractTPQStatementParameter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/AbstractTPQStatementParameter.java
new file mode 100644
index 0000000..7588f06
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/AbstractTPQStatementParameter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.parameter;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQueryParameter;
+
+/**
+ * AbstractTQueryTemplateType holds the templateType key value.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 22, 2015
+ */
+public abstract class AbstractTPQStatementParameter implements TPQStatementParameter {
+
+ private final String templateType;
+
+ /**
+ * Creates the abstract template type.
+ * @param templateType The templateType key.
+ */
+ public AbstractTPQStatementParameter(String templateType) {
+ Validate.notNull(templateType, "templateType is null.");
+ this.templateType=templateType;
+ }
+
+ @Override
+ public final String getParameterType() {
+ return templateType;
+ }
+
+ @Override
+ public void prepareValidate(TPQueryParameter param, Class> valueType, Object paramValue) {
+ }
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/TPQStatementParameter.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/TPQStatementParameter.java
new file mode 100644
index 0000000..55cc251
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/TPQStatementParameter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.parameter;
+
+import net.forwardfire.tpquery.model.TPQueryParameter;
+import net.forwardfire.tpquery.statement.TPQStatementWriter;
+
+/**
+ * writes,validate and creates cacheKey for parameter type.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 16, 2015
+ */
+public interface TPQStatementParameter {
+
+ /**
+ * @return The parameter type to handle.
+ */
+ String getParameterType();
+
+ /**
+ * Validates the parameter value.
+ * @param param The query parameter.
+ * @param valueType The resolved query parameter type.
+ * @param value The parameter value.
+ */
+ void prepareValidate(TPQueryParameter param, Class> valueType, Object value);
+
+ /**
+ * Appends cache key for this parameter if needed.
+ * @param keyBuf The cacheKey buffer to append to.
+ * @param param The query parameter.
+ * @param value The query parameter value.
+ * @return returns true if parameter is cachable, false if not.
+ */
+ boolean prepareCacheKey(StringBuilder keyBuf,TPQueryParameter param, Object value);
+
+ /**
+ * Appends the query parameter to the writer.
+ * @param queryWriter The statement writer.
+ * @param param The query parameter.
+ * @param value The parameter value.
+ */
+ void prepareParameter(TPQStatementWriter queryWriter, TPQueryParameter param, Object value);
+}
diff --git a/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/TPQStatementParameterList.java b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/TPQStatementParameterList.java
new file mode 100644
index 0000000..f945fc2
--- /dev/null
+++ b/tpquery-store/src/main/java/net/forwardfire/tpquery/statement/parameter/TPQStatementParameterList.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013-2015, Willem Cazander
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.forwardfire.tpquery.statement.parameter;
+
+import java.util.List;
+
+import org.apache.commons.lang3.Validate;
+
+import net.forwardfire.tpquery.model.TPQueryParameter;
+import net.forwardfire.tpquery.statement.TPQStatementWriter;
+
+/**
+ * Appends the query parameter list values to the writer.
+ *
+ * @author Willem Cazander
+ * @version 1.0 May 17, 2015
+ */
+public class TPQStatementParameterList extends AbstractTPQStatementParameter {
+
+ /**
+ * Creates the parameter list template type.
+ * @param templateType The templateType key.
+ */
+ public TPQStatementParameterList(String templateType) {
+ super(templateType);
+ }
+
+ @Override
+ public void prepareValidate(TPQueryParameter param, Class> valueType, Object value) {
+ Validate.notNull(value, "List parameter requires non null value.");
+ Validate.isInstanceOf(List.class, value, "List parameter requires java.util.List type not: %s",value.getClass().getName());
+ List> valueList = (List>)value;
+ Validate.isTrue(!valueList.isEmpty(), "List parameter requires none empty list.");
+ Object checkFirst = valueList.get(0);
+ Validate.isInstanceOf(valueType, checkFirst , "List parameter value with name: "+param.getName()+" has wong type: "+param.getValueType()+" but is: "+checkFirst.getClass().getName());
+ }
+
+ @Override
+ public boolean prepareCacheKey(StringBuilder keyBuf,TPQueryParameter param, Object value) {
+ keyBuf.append(((List>)value).size());
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void prepareParameter(TPQStatementWriter queryWriter, TPQueryParameter param, Object value) {
+ writeList(queryWriter, param.getName(), (List