Commit eda4c510 authored by Nico Mack's avatar Nico Mack

Added array extrapolation feature to SqlExecutor

parent d3a27161
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>lu.list.itis.dkd.tui</groupId> <groupId>lu.list.itis.dkd.tui</groupId>
<artifactId>tulip-cps</artifactId> <artifactId>tulip-cps</artifactId>
<version>1.4.0</version> <version>1.5.0</version>
<name>TULIP Complex Problem Solving</name> <name>TULIP Complex Problem Solving</name>
<licenses> <licenses>
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
<dependency> <dependency>
<groupId>lu.list.itis.dkd.tui</groupId> <groupId>lu.list.itis.dkd.tui</groupId>
<artifactId>tulip</artifactId> <artifactId>tulip</artifactId>
<version>2.4.0</version> <version>2.5.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>maven2.dk.ange</groupId> <groupId>maven2.dk.ange</groupId>
...@@ -67,12 +67,12 @@ ...@@ -67,12 +67,12 @@
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId> <artifactId>log4j-api</artifactId>
<version>2.8</version> <version>2.8.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
<version>2.8</version> <version>2.8.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
......
...@@ -211,6 +211,8 @@ public class EquationSystemBuilder { ...@@ -211,6 +211,8 @@ public class EquationSystemBuilder {
variable = (Variable<T>) Class.forName(variableClass) variable = (Variable<T>) Class.forName(variableClass)
.getConstructor(String.class, String.class) .getConstructor(String.class, String.class)
.newInstance(name, value); .newInstance(name, value);
if (!Strings.isNullOrEmpty(value))
variable.setValue(variable.valueFromString(value));
break; break;
case Externalization.SPATIAL_TYPE: case Externalization.SPATIAL_TYPE:
...@@ -230,6 +232,8 @@ public class EquationSystemBuilder { ...@@ -230,6 +232,8 @@ public class EquationSystemBuilder {
variable = (Variable<T>) Class.forName(variableClass) variable = (Variable<T>) Class.forName(variableClass)
.getConstructor(String.class, String.class) .getConstructor(String.class, String.class)
.newInstance(name, unit); .newInstance(name, unit);
if (!Strings.isNullOrEmpty(value))
variable.setValue(variable.valueFromString(value));
break; break;
} }
......
...@@ -22,13 +22,15 @@ import org.slf4j.Logger; ...@@ -22,13 +22,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.beans.PropertyVetoException; import java.beans.PropertyVetoException;
import java.sql.Array;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -59,11 +61,24 @@ public class SqlExecutor extends Executor { ...@@ -59,11 +61,24 @@ public class SqlExecutor extends Executor {
private static final String SQL_USER_NAME = "sql.user.name"; //$NON-NLS-1$ private static final String SQL_USER_NAME = "sql.user.name"; //$NON-NLS-1$
private static final String SQL_USER_PASSWORD = "sql.user.password"; //$NON-NLS-1$ private static final String SQL_USER_PASSWORD = "sql.user.password"; //$NON-NLS-1$
private static final Pattern SQL_VAR_PATTERN = Pattern.compile("\\$\\{([a-z0-9\\-_]+)\\}", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ private static final Pattern SQL_VAR_PATTERN = Pattern.compile("([\\$@])\\{([a-z0-9\\-_]+)\\}", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
private static Logger LOGGER = LoggerFactory.getLogger(SqlExecutor.class.getSimpleName()); private static Logger LOGGER = LoggerFactory.getLogger(SqlExecutor.class.getSimpleName());
private static final int MAX_CONNECTION_ATTEMPTS = 3; private static final int MAX_CONNECTION_ATTEMPTS = 3;
private static HashMap<Class<?>, String> JavaToJdbcMapping = new HashMap<>();
static {
JavaToJdbcMapping.put(String.class, "varchar"); //$NON-NLS-1$
JavaToJdbcMapping.put(Integer.class, "integer"); //$NON-NLS-1$
JavaToJdbcMapping.put(Double.class, "double"); //$NON-NLS-1$
JavaToJdbcMapping.put(Float.class, "real"); //$NON-NLS-1$
JavaToJdbcMapping.put(Date.class, "timestamp"); //$NON-NLS-1$
JavaToJdbcMapping.put(Time.class, "time"); //$NON-NLS-1$
}
private static final String SCALAR = "$"; //$NON-NLS-1$
private static final String VECTOR = "@"; //$NON-NLS-1$
// *************************************************************************** // ***************************************************************************
// * Constructor(s) * // * Constructor(s) *
// *************************************************************************** // ***************************************************************************
...@@ -160,11 +175,13 @@ public class SqlExecutor extends Executor { ...@@ -160,11 +175,13 @@ public class SqlExecutor extends Executor {
*/ */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
private String interpolate(String query, List<String> placeholders, boolean positionalParameters) { private String interpolate(String query, List<String> placeholders, Map<String, Object> parameters, boolean positionalParameters) {
Matcher interpolator; Matcher interpolator;
String type;
String variable; String variable;
int position = 0; int position = 0;
StringBuffer interpolated; StringBuffer interpolated;
int index = 1;
placeholders.clear(); placeholders.clear();
interpolator = SQL_VAR_PATTERN.matcher(query); interpolator = SQL_VAR_PATTERN.matcher(query);
...@@ -173,13 +190,42 @@ public class SqlExecutor extends Executor { ...@@ -173,13 +190,42 @@ public class SqlExecutor extends Executor {
while (interpolator.find()) { while (interpolator.find()) {
interpolated.append(query.substring(position, interpolator.start())); interpolated.append(query.substring(position, interpolator.start()));
position = interpolator.start(); position = interpolator.start();
variable = interpolator.group(1); type = interpolator.group(1);
variable = interpolator.group(2);
if ((variable != null) && (variable.length() > 0)) { if ((variable != null) && (variable.length() > 0)) {
placeholders.add(variable); placeholders.add(variable);
interpolated.append("?"); //$NON-NLS-1$
if (positionalParameters) if (SCALAR.equals(type)) {
interpolated.append(placeholders.size()); interpolated.append("?"); //$NON-NLS-1$
if (positionalParameters)
interpolated.append(index++);
}
if (VECTOR.equals(type)) {
Object value = parameters.get(variable);
if (value instanceof Collection) {
Collection<?> collection = (Collection<?>) value;
String separator = "";
if (collection.size() > 0) {
for (int count = 0; count < collection.size(); count++) {
interpolated.append(separator);
interpolated.append("?");
if (positionalParameters)
interpolated.append(index++);
separator = ",";
}
} else {
interpolated.append("?"); //$NON-NLS-1$
if (positionalParameters)
interpolated.append(index++);
}
} else {
interpolated.append("?"); //$NON-NLS-1$
if (positionalParameters)
interpolated.append(index++);
}
}
} else { } else {
interpolated.append(interpolated.substring(interpolator.start(), interpolator.end())); interpolated.append(interpolated.substring(interpolator.start(), interpolator.end()));
} }
...@@ -197,14 +243,22 @@ public class SqlExecutor extends Executor { ...@@ -197,14 +243,22 @@ public class SqlExecutor extends Executor {
for (String placeholder : placeholders) { for (String placeholder : placeholders) {
if (context.containsKey(placeholder)) { if (context.containsKey(placeholder)) {
Object value = context.get(placeholder); Object value = context.get(placeholder);
if (value instanceof Array) if (value instanceof Collection) {
statement.setArray(index, (Array) value); Collection<?> collection = (Collection<?>) value;
else if (collection.size() > 0) {
statement.setObject(index, value); for (Object item : collection) {
statement.setObject(index++, item);
}
} else {
statement.setObject(index++, null);
}
} else {
statement.setObject(index++, value);
}
} else { } else {
LOGGER.warn("Query requires the parameter {} which is not available in context!", placeholder); //$NON-NLS-1$ LOGGER.warn("Query requires the parameter {} which is not available in context!", placeholder); //$NON-NLS-1$
} }
index++;
} }
return statement; return statement;
} }
...@@ -304,7 +358,7 @@ public class SqlExecutor extends Executor { ...@@ -304,7 +358,7 @@ public class SqlExecutor extends Executor {
long elapsed = System.currentTimeMillis(); long elapsed = System.currentTimeMillis();
Connection connection = this.getConnectionFromPool(); Connection connection = this.getConnectionFromPool();
List<String> variables = new ArrayList<String>(); List<String> variables = new ArrayList<String>();
String queryString = this.interpolate(script, variables, false); String queryString = this.interpolate(script, variables, this.parameters, false);
boolean success = false; boolean success = false;
if (connection != null) { if (connection != null) {
......
...@@ -21,6 +21,7 @@ import java.util.Collection; ...@@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
import java.util.regex.Pattern;
/** /**
* @author mack * @author mack
...@@ -28,13 +29,40 @@ import java.util.Vector; ...@@ -28,13 +29,40 @@ import java.util.Vector;
* @version [major].[minor].[micro] * @version [major].[minor].[micro]
* @param <B> * @param <B>
*/ */
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class VectorVariable<B> extends Variable<List<B>> implements Collection<B> { public class VectorVariable<B> extends Variable<List<B>> implements Collection<B> {
private static final Pattern VECTOR_PATTERN = Pattern.compile("\\[\\s*(.*?)\\s*\\]", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
private static final Pattern VECTOR_SPLITTER_PATTERN = Pattern.compile("([+-]?[a-z0-9\\._]+)(\\s*,[+-]?[a-z0-9\\._]+)*", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
public VectorVariable(String name, String unit) { public VectorVariable(String name, String unit) {
super(Externalization.VECTOR_TYPE, name, unit); super(Externalization.VECTOR_TYPE, name, unit);
value = new ArrayList<B>(); value = new ArrayList<B>();
} }
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives *
// ***************************************************************************
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
public Class<?> getClassOfValues() { public Class<?> getClassOfValues() {
if (!value.isEmpty()) { if (!value.isEmpty()) {
return value.get(0).getClass(); return value.get(0).getClass();
...@@ -160,8 +188,23 @@ public class VectorVariable<B> extends Variable<List<B>> implements Collection<B ...@@ -160,8 +188,23 @@ public class VectorVariable<B> extends Variable<List<B>> implements Collection<B
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public List<B> valueFromString(String stringValue) { public List<B> valueFromString(String stringValue) {
// TODO Auto-generated method stub if (stringValue == null)
return null; return null;
List<B> values = new ArrayList<>();
// First check whether string complies with array string representation.
// Matcher arrayMatcher = VECTOR_PATTERN.matcher(stringValue);
// if (arrayMatcher.matches()) {
// Matcher arraySplitter = VECTOR_SPLITTER_PATTERN.matcher(arrayMatcher.group(1));
// if (arraySplitter.matches()) {
// for (int i = 0; i < arraySplitter.groupCount(); i++) {
// values.add((B) arraySplitter.group(i));
// }
// }
// }
return values;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2017. All rights reserved. If you wish
* to use this code for any purpose, please contact the author(s).
*
* 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 OWNER 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 lu.list.itis.dkd.tui.cps.variable;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
*/
public class VectorVariableTest {
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {}
@Test
public void test() {
VectorVariable<Double> variable = new VectorVariable<>("test", "n/a");
List<Double> fromString = variable.valueFromString("[ 1, 2, 3.5, -0.443503]");
assertEquals(4, fromString.size());
assertEquals(1d, fromString.get(0).doubleValue(), 0.0001);
assertEquals(2d, fromString.get(1).doubleValue(), 0.0001);
assertEquals(3.5d, fromString.get(2).doubleValue(), 0.0001);
assertEquals(-0.443503d, fromString.get(3).doubleValue(), 0.0001);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment