![JAR search and dependency download from the Maven repository](/logo.png)
de.tsl2.nano.h5.expression.Query Maven / Gradle / Ivy
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom, Thomas Schneider
* created on: 25.02.2014
*
* Copyright: (c) Thomas Schneider 2014, all rights reserved
*/
package de.tsl2.nano.h5.expression;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementMap;
import de.tsl2.nano.bean.BeanContainer;
import de.tsl2.nano.core.ENV;
import de.tsl2.nano.core.log.LogFactory;
import de.tsl2.nano.core.util.StringUtil;
import de.tsl2.nano.core.util.Util;
import de.tsl2.nano.execution.IPRunnable;
import de.tsl2.nano.service.util.ServiceUtil;
import de.tsl2.nano.specification.AbstractRunnable;
import de.tsl2.nano.specification.IPrefixed;
/**
* class to execute sql statements. not an inheritance of AbstractRunnable in cause of not having constraints in its
* parameter map.
*
* @author Tom, Thomas Schneider
* @version $Revision$
*/
public class Query implements IPRunnable>, IPrefixed {
/** serialVersionUID */
private static final long serialVersionUID = -9199837113877884921L;
private static final Log LOG = LogFactory.getLog(Query.class);
/** full column expression for one column */
private static final String SQL_COL = "(^|\\,)\\s*([^,]+)(\\s+[Aa][Ss]\\s+(\\w+))?";
/** sql parameter */
private static final String SQL_PAR = "[:]([\\w._-]+)";
/** sql function */
private static final String SQL_FCT = "(\\w+)\\([^\\(\\)]+\\)";
/** column name */
private static final String SQL_NAM = ".*(\\w+)";
/** string literal */
private static final String SQL_LIT = "['\"][^'\"]*['\"]";
/** one or more concatenations */
private static final String SQL_CON = "[^,]+[|]{2}";
/** column path (if schema, etc. where given) */
private static final String SQL_PAT = "(\\w+[.])+";
@Attribute
String name;
@Element(data = true)
String operation;
@Attribute
boolean nativeQuery;
@ElementMap(entry = "parameter", attribute = true, inline = true, keyType = String.class, key = "name", value = "type", required = false)
Map parameter;
private transient ArrayList columnNames;
/**
* constructor
*/
public Query() {
}
public Query(String name, String query) {
this(name, query, null);
}
public Query(String name, String query, Map parameter) {
this(name, query, true, parameter);
}
/**
* constructor
*
* @param name
* @param query
* @param parameter
*/
public Query(String name, String query, boolean nativeQuery, Map parameter) {
super();
this.name = name;
this.operation = query;
this.nativeQuery = nativeQuery;
this.parameter = parameter;
}
@SuppressWarnings("unchecked")
@Override
public RESULT run(Map context, Object... extArgs) {
//workaround for hibernate/query not allowing parameter with dots
Set pars = getParameter().keySet();
String op = operation.replaceAll("--.*", "");
Map args = checkedArguments(context, ENV.get("app.mode.strict", false));
String sqlvar;
for (String p : pars) {
sqlvar = p.replace('.', 'X');
if (parameter.get(p) != null) {
args.put(sqlvar, parameter.get(p));
if (!context.containsKey(p))
context.put(p, parameter.get(p));
} else if (context.containsKey(p))
args.put(sqlvar, context.get(p));
op = op.replace(":" + p, ":" + sqlvar);
}
//do the job
return (RESULT) (ServiceUtil.isExcecutionStatement(op) ? BeanContainer.instance().executeStmt(op, nativeQuery, args.values().toArray())
: BeanContainer.instance().getBeansByQuery(op, nativeQuery, args));
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getQuery() {
return operation;
}
public void setQuery(String query) {
operation = query;
columnNames = null;
parameter = null;
}
@Override
public Map getParameter() {
if (parameter == null) {
parameter = new LinkedHashMap();
String p;
//remove temporary all comments
String op = operation.replaceAll("--.*", "");
//we allow both: the named query syntax and the most java used ant-like-variables
op = operation.replace("${", ":").replace("}", "");
//redundant: persist the cleaned sql-query-parameter
operation = operation.replace("${", ":").replace("}", "");
StringBuilder q = new StringBuilder(op);
while ((!Util.isEmpty(p = StringUtil.extract(q, SQL_PAR, "")))) {
parameter.put(p.substring(1), null);
}
}
return parameter;
}
/**
* evaluates the query's column names through the select-columns having an 'as' expression.
*
* e.g. 'select name, type as Type from...
* will have the column 'Type'.
*
* @return
*/
public List getColumnNames() {
if (columnNames == null) {
columnNames = new ArrayList();
String p;
//get the full selection header and eliminate literals, functions and concatenations
String select = StringUtil.substring(operation, "select ", "from ");
select = select.replaceAll(SQL_LIT, "");
select = select.replaceAll(SQL_PAT, "");
select = select.replaceAll(SQL_CON, "");
//TODO: capturing group 1 is not used! why?
select = select.replaceAll(SQL_FCT, "$1");
StringBuilder q = new StringBuilder(select);
while ((!Util.isEmpty(p = StringUtil.extract(q, SQL_COL, "", 0, 0)))) {
String as = StringUtil.extract(p, "\\s+[Aa][Ss]\\s+");
columnNames.add(!Util.isEmpty(as) && p.contains(as)
? StringUtil.substring(p, as, null).trim()
: StringUtil.substring(StringUtil.substring(p, ",", null), ".", null, true).trim());
}
if (LOG.isDebugEnabled())
LOG.debug(Arrays.toString(columnNames.toArray()));
}
return columnNames;
}
@Override
public Map checkedArguments(Map arguments, boolean strict) {
boolean asSequence = AbstractRunnable.asSequence(arguments);
Map args = new LinkedHashMap();
if (parameter.isEmpty()) //only defined parameters are allowed - otherwise we get an exception by jpa query implementation
return args;
Set keySet = arguments.keySet();
Set parameterKeys = parameter.keySet();
Iterator
© 2015 - 2025 Weber Informatics LLC | Privacy Policy