/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.framework.sql;
import com.esri.gpt.framework.util.Val;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* Aids in the process of binding HTTP request parameters to SQL expressions.
*/
public class HttpExpressionBinder extends ExpressionBinder {
/** class variables ========================================================= */
/** Parameter type: "Double" */
public static final String PARAMETERTYPE_DOUBLE = "Double";
/** Parameter type: "Integer" */
public static final String PARAMETERTYPE_INTEGER = "Integer";
/** Parameter type: "String" */
public static final String PARAMETERTYPE_STRING = "String";
/** instance variables ====================================================== */
private Map<String,String[]> parameters = new HashMap<String,String[]>();
private HttpServletRequest request;
/** constructors ============================================================ */
/**
* Constructor
* @param request the HTTP servlet rquest
*/
@SuppressWarnings(value = "unchecked")
public HttpExpressionBinder(HttpServletRequest request) {
this.request = request;
// marshal the servlet parameter map into a map with low case keys
Enumeration enNames = request.getParameterNames();
while (enNames.hasMoreElements()) {
String key = (String)enNames.nextElement();
parameters.put(key.toLowerCase(),request.getParameterValues(key));
}
}
/** methods ================================================================= */
/**
* Gets the first object value associated with a parameter name.
* <br/>The parameterType is used to convert HTTP key-value pair strings to an
* object of the supplied parameter type.
* @param parameter the parameter name
* @param parameterType the parameter type (HttpExpressionBinder.PARAMETERTYPE_*)
* @return the converted object value (null if none)
*/
private Object getObjectValue(String parameter, String parameterType) {
String value = Val.chkStr(getParameter(parameter));
if (value.length() > 0) {
return this.makeObjectValue(value,parameterType);
} else {
return null;
}
}
/**
* Gets the list of object values associated with a parameter name.
* <br/>The parameterType is used to convert HTTP key-value pair strings to an
* object of the supplied parameter type.
* @param parameter the parameter name
* @paaram delimiter a delimiter to tokenize values (can be null)
* @param parameterType the parameter type (HttpExpressionBinder.PARAMETERTYPE_*)
* @return the converted object values (empty list if none were located)
*/
private List<Object> getObjectValues(String parameter, String delimiter, String parameterType) {
String[] values = this.parameters.get(parameter.toLowerCase());
List<Object> oValues = new ArrayList<Object>();
if (values != null) {
for (String value: values) {
value = Val.chkStr(value);
if (value.length() > 0) {
if ((delimiter != null) && (delimiter.length() > 0)) {
String[] tokens = Val.tokenize(value,delimiter);
for (String token: tokens) {
String sToken = Val.chkStr(token);
if (sToken.length() > 0) {
oValues.add(this.makeObjectValue(sToken,parameterType));
}
}
} else {
oValues.add(this.makeObjectValue(value,parameterType));
}
}
}
}
return oValues;
}
/**
* Gets the first value associated with a parameter name.
* @param parameter the parameter name
* @return the parameter value (null if none)
*/
private String getParameter(String parameter) {
String[] values = this.getParameterValues(parameter);
if (values.length > 0) {
return values[0];
} else {
return null;
}
}
/**
* Gets the array of values associated with a parameter name.
* @param parameter the parameter name
* @return the parameter values array (empty array if none were located)
*/
private String[] getParameterValues(String parameter) {
String[] values = this.parameters.get(parameter.toLowerCase());
if (values != null) {
return values;
} else {
return new String[0];
}
}
/**
* Makes an object from a parameter value.
* <br/>The parameterType is used to convert HTTP key-value pair strings to an
* object of the supplied parameter type.
* @param parameterValue the parameter value
* @param parameterType the parameter type (HttpExpressionBinder.PARAMETERTYPE_*)
* @return the converted object value
*/
private Object makeObjectValue(String parameterValue, String parameterType) {
Object value = null;
try {
if (parameterType.equalsIgnoreCase(HttpExpressionBinder.PARAMETERTYPE_DOUBLE)) {
value = new Double(parameterValue);
} else if (parameterType.equalsIgnoreCase(HttpExpressionBinder.PARAMETERTYPE_INTEGER)) {
value = new Integer(parameterValue);
} else if (parameterType.equalsIgnoreCase(HttpExpressionBinder.PARAMETERTYPE_STRING)) {
value = new String(parameterValue);
} else {
value = "";
}
} catch (NumberFormatException nfe) {
value = "";
}
return value;
}
/**
* Parses the HTTP resquest, binding a parameter value to an SQL field.
* @param parameter the HTTP request parameter name
* @param field the SQL field name
* @param operator the SQL operator examples: =, !=, >, >=, <, <=, LIKE, ...
* @param parameterType the parameter type (HttpExpressionBinder.PARAMETERTYPE_*)
*/
public void parse(String parameter, String field, String operator, String parameterType) {
Object binding = this.getObjectValue(parameter,parameterType);
if (binding != null) {
this.addBinding(field,operator,binding);
}
}
/**
* Parses the HTTP resquest, binding parameter values to an SQL field.
* <br/>This method considers multiple valuers per parameter name.
* <br/>The values collection is connected by logical "OR" operators.
* @param parameter the HTTP request parameter name
* @param field the SQL field name
* @param operator the SQL operator examples: =, !=, >, >=, <, <=, LIKE, ...
* @param delimiter a delimiter to tokenize values (can be null)
* @param parameterType the parameter type (HttpExpressionBinder.PARAMETERTYPE_*)
*/
public void parse(String parameter, String field, String operator, String delimiter, String parameterType) {
List<Object> bindings = this.getObjectValues(parameter,delimiter,parameterType);
if (bindings != null) {
this.addBindings(field,operator,bindings.toArray());
}
}
/**
* Parses the HTTP resquest, binding a parameter value to an SQL field.
* <br/>This method is useful for VARCHAR type SQL fields.
* @param parameter the HTTP request parameter name
* @param field the SQL field name
* @param forceUpper force an upper case comparison
* @param forceLike for an SQL LIKE operator
*/
public void parse(String parameter, String field, boolean forceUpper, boolean forceLike) {
String value = Val.chkStr(getParameter(parameter));
if (value.length() > 0) {
this.addBinding(field,value,forceUpper,forceLike);
}
}
/**
* Parses the HTTP resquest, binding parameter values to an SQL field.
* <br/>This method considers multiple valuers per parameter name.
* <br/>The values collection is connected by logical "OR" operators.
* <br/>This method is useful for VARCHAR type SQL fields.
* @param parameter the HTTP request parameter name
* @param field the SQL field name
* @param delimiter a delimiter to tokenize values (can be null)
* @param forceUpper force an upper case comparison
* @param forceLike for an SQL LIKE operator
*/
public void parse(String parameter, String field, String delimiter, boolean forceUpper, boolean forceLike) {
String parameterType = HttpExpressionBinder.PARAMETERTYPE_STRING;
List<Object> bindings = this.getObjectValues(parameter,delimiter,parameterType);
if (bindings != null) {
this.addBindings(field,bindings.toArray(new String[0]),forceUpper,forceLike);
}
}
}