blob: f8df2c7857f6d967bd32b904fb15ec165e0e32bf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 org.apache.pirk.utils;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Text;
import org.apache.pirk.inputformat.hadoop.TextArrayWritable;
import org.apache.pirk.schema.data.DataSchema;
import org.apache.pirk.schema.data.partitioner.IPDataPartitioner;
import org.elasticsearch.hadoop.mr.WritableArrayWritable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class used for URI query parsing
* <p>
* Query of the form @{code ?q=<queryField>:<queryTerm>}
* <p>
* TODO: Use Lucene's query parsing?... Make this lots lots better...
*
*/
public class QueryParserUtils
{
private static final Logger logger = LoggerFactory.getLogger(QueryParserUtils.class);
/**
* Given a URI query string, checks to see if the given document satisfies the query
* <p>
* ...Very hacky...
* <p>
* NOTE: Assumes that MapWritable keys are Text objects and values are Text or TextArrayWritable objects
* <p>
* NOTE: Support for list fields (values) is provided for checkRecord with Map<String, Object> and checkRecord with MapWritable containing
* WritableArrayWritable types for array values (vs. json string list representation)
* <p>
* NOTE: @ symbol represents flag ignore case sensitivity used after field (e.g. user_agent@:*searchparam*)
* <p>
* NOTE: Assumes that all AND booleans come before any OR booleans - ADD @ case sensitivity support for range queries
*
*/
public static boolean checkRecord(String uriQuery, MapWritable doc, DataSchema dataSchema)
{
boolean satisfiesQuery = true;
logger.debug("uriQuery = " + uriQuery);
uriQuery = uriQuery.substring(3); // strip the beginning query tag '?q='
logger.debug("uriQuery = " + uriQuery);
if (uriQuery.equals("*"))
{
return true;
}
String[] queryTokens = uriQuery.split("\\+(?=AND)|\\+(?=OR)|\\+(?=[a-z])"); // booleans of the form +AND+, +OR+, don't split on +T0+
int index = 0;
String item;
while (index < queryTokens.length)
{
boolean ignoreCase = false;
item = queryTokens[index];
logger.debug("item = " + item);
String[] itemTokens = item.split(":", 2); // There are two components <field>:<query>
logger.debug("itemTokens[0] = " + itemTokens[0] + " itemTokens[1] = " + itemTokens[1]);
// check for ignore case flag
if (itemTokens[0].endsWith("@"))
{
ignoreCase = true;
logger.debug("ignore case = true");
itemTokens[0] = itemTokens[0].replaceAll("@", ""); // strip flag
logger.debug("itemTokens[0]:" + itemTokens[0]);
}
Object value = doc.get(new Text(itemTokens[0]));
if (value != null) // if the field is not present, a null Writable is returned
{
if (itemTokens[1].startsWith("[")) // Inclusive range query
{
if (value instanceof Text)
{
if (!checkRangeQuery(true, itemTokens[0], itemTokens[1], value.toString(), dataSchema))
{
logger.debug("checkRangeQuery returned false");
satisfiesQuery = false;
}
}
else if (value instanceof TextArrayWritable)
{
String[] elements = ((TextArrayWritable) value).toStrings();
boolean oneSatisfied = false;
for (String element : elements)
{
if (checkRangeQuery(true, itemTokens[0], itemTokens[1], element, dataSchema))
{
logger.debug("checkRangeQuery returned true");
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
else if (itemTokens[1].startsWith("{")) // Exclusive range query
{
if (value instanceof Text)
{
if (!checkRangeQuery(false, itemTokens[0], itemTokens[1], value.toString(), dataSchema))
{
logger.debug("checkRangeQuery returned false");
satisfiesQuery = false;
}
}
else if (value instanceof TextArrayWritable)
{
String[] elements = ((TextArrayWritable) value).toStrings();
boolean oneSatisfied = false;
for (String element : elements)
{
if (checkRangeQuery(false, itemTokens[0], itemTokens[1], element, dataSchema))
{
logger.debug("checkRangeQuery returned true");
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
else
// Not a range query
{
if (value instanceof Text)
{
String valueString = value.toString();
if (ignoreCase)
{ // Case insensitivity
logger.debug("not a range query; itemstoken1:" + itemTokens[1]);
itemTokens[1] = itemTokens[1].toLowerCase();
valueString = valueString.toLowerCase();
logger.debug("valuestring after:" + valueString);
}
if (itemTokens[1].contains("*") || itemTokens[1].contains("?")) // Wildcard match
{
logger.debug("itemTokens[1] = " + itemTokens[1] + " contains wildcard");
if (!Pattern.matches(wildcardToRegex(itemTokens[1]), valueString))
{
logger.debug("stringValue = " + valueString + " did not satisfy itemTokens[1] = " + itemTokens[1]);
satisfiesQuery = false;
}
logger.debug("stringValue = " + valueString + " did satisfy itemTokens[1] = " + itemTokens[1]);
}
else if (!(valueString).equals(itemTokens[1])) // Single value match
{
logger.debug("We do not have a single value match: stringValue " + valueString + " != itemTokens[1] = " + itemTokens[1]);
satisfiesQuery = false;
}
}
else if (value instanceof TextArrayWritable)
{
String[] elements = ((TextArrayWritable) value).toStrings();
logger.debug("elements.size() = " + elements.length);
boolean oneSatisfied = false;
for (String element : elements)
{
if (ignoreCase)
{ // Case insensitivity
itemTokens[1] = itemTokens[1].toLowerCase();
logger.debug("waw: itemtoken1 after:" + itemTokens[1]);
element = element.toLowerCase();
logger.debug("element after:" + element);
}
logger.debug("element: " + element);
if (itemTokens[1].contains("*") || itemTokens[1].contains("?")) // Wildcard match
{
logger.debug("itemTokens[1] = " + itemTokens[1] + " contains wildcard");
if (Pattern.matches(wildcardToRegex(itemTokens[1]), element))
{
logger.debug("stringValue = " + element + " satisfied itemTokens[1] = " + itemTokens[1]);
oneSatisfied = true;
break;
}
}
else if (element.equals(itemTokens[1])) // Single value match
{
logger.debug("We have a single value match: stringValue " + element + " = itemTokens[1] = " + itemTokens[1]);
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
}
else
{
satisfiesQuery = false; // add fix - account for case if query field does not exist
}
++index; // Try to pick up the boolean operators
if (index < (queryTokens.length - 1))
{
if (queryTokens[index].equals("AND")) // Do nothing and keep going
{
if (!satisfiesQuery)
{
break;
}
++index;
item = queryTokens[index];
}
else if (queryTokens[index].equals("OR")) // Assume all OR's occur after all AND's
{
if (satisfiesQuery) // if we passed the query and it is not the first term
{
break;
}
else
{
++index;
item = queryTokens[index];
satisfiesQuery = true; // reset so that we pick up matches for the next term
}
}
else if (!satisfiesQuery)
{
logger.debug("Does not satisfy the query and no boolean ops next...");
break;
}
}
}
return satisfiesQuery;
}
@SuppressWarnings("unchecked")
public static boolean checkRecord(String uriQuery, Map<String,Object> doc, DataSchema dataSchema)
{
boolean satisfiesQuery = true;
logger.debug("uriQuery = " + uriQuery);
uriQuery = uriQuery.substring(3); // strip the beginning query tag '?q='
logger.debug("uriQuery = " + uriQuery);
if (uriQuery.equals("*"))
{
return true;
}
String[] queryTokens = uriQuery.split("\\+(?=AND)|\\+(?=OR)|\\+(?=[a-z])"); // booleans of the form +AND+, +OR+, don't split on +T0+
int index = 0;
String item;
while (index < queryTokens.length)
{
item = queryTokens[index];
logger.debug("item = " + item);
String[] itemTokens = item.split(":", 2); // There are two components <field>:<query>
logger.debug("itemTokens[0] = " + itemTokens[0] + " itemTokens[1] = " + itemTokens[1]);
boolean ignoreCase = false;
// check for ignore case flag
if (itemTokens[0].endsWith("@"))
{
ignoreCase = true;
itemTokens[0] = itemTokens[0].replaceAll("@", ""); // strip case flag
logger.debug("ignore case: itemTokens[0] = " + itemTokens[0] + " itemTokens[1] = " + itemTokens[1]);
}
Object value = doc.get(itemTokens[0]); // handle array answers
if (value != null) // if the field is not present, a null Writable is returned
{
if (itemTokens[1].startsWith("[")) // Inclusive range query
{
if (value instanceof String)
{
if (ignoreCase)
{ // case insensitivity
itemTokens[1] = itemTokens[1].toLowerCase();
value = value.toString().toLowerCase();
}
if (!checkRangeQuery(true, itemTokens[0], itemTokens[1], (String) value, dataSchema))
{
logger.debug("checkRangeQuery returned false");
satisfiesQuery = false;
}
}
else if (value instanceof ArrayList)
{
boolean oneSatisfied = false;
for (String element : (ArrayList<String>) value)
{
if (checkRangeQuery(true, itemTokens[0], itemTokens[1], element, dataSchema))
{
logger.debug("checkRangeQuery returned true");
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
else if (itemTokens[1].startsWith("{")) // Exclusive range query
{
if (value instanceof String)
{
if (!checkRangeQuery(false, itemTokens[0], itemTokens[1], (String) value, dataSchema))
{
logger.debug("checkRangeQuery returned false");
satisfiesQuery = false;
}
}
else if (value instanceof ArrayList)
{
boolean oneSatisfied = false;
for (String element : (ArrayList<String>) value)
{
if (ignoreCase)
{
itemTokens[1] = itemTokens[1].toLowerCase();
element = element.toLowerCase();
}
if (checkRangeQuery(false, itemTokens[0], itemTokens[1], element, dataSchema))
{
logger.debug("checkRangeQuery returned true");
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
else
// Not a range query
{
if (value instanceof String)
{
if (ignoreCase)
{
itemTokens[1] = itemTokens[1].toLowerCase();
value = value.toString().toLowerCase();
}
if (itemTokens[1].contains("*") || itemTokens[1].contains("?")) // Wildcard match
{
logger.debug("itemTokens[1] = " + itemTokens[1] + " contains wildcard");
if (!Pattern.matches(wildcardToRegex(itemTokens[1]), (String) value))
{
logger.debug("stringValue = " + value + " did not satisfy itemTokens[1] = " + itemTokens[1]);
satisfiesQuery = false;
}
logger.debug("stringValue = " + value + " did satisfy itemTokens[1] = " + itemTokens[1]);
}
else if (!(value).equals(itemTokens[1])) // Single value match
{
logger.debug("We do not have a single value match: stringValue " + value + " != itemTokens[1] = " + itemTokens[1]);
satisfiesQuery = false;
}
}
else if (value instanceof ArrayList)
{
boolean oneSatisfied = false;
for (String element : (ArrayList<String>) value)
{
logger.debug("element = " + element);
if (ignoreCase)
{ // case insensitivity
itemTokens[1] = itemTokens[1].toLowerCase();
element = element.toLowerCase();
}
if (itemTokens[1].contains("*") || itemTokens[1].contains("?")) // Wildcard match
{
logger.debug("itemTokens[1] = " + itemTokens[1] + " contains wildcard");
if (Pattern.matches(wildcardToRegex(itemTokens[1]), element))
{
logger.debug("stringValue = " + element + " satisfied itemTokens[1] = " + itemTokens[1]);
oneSatisfied = true;
break;
}
}
else if (element.equals(itemTokens[1])) // Single value match
{
logger.debug("We have a single value match: stringValue " + element + " = itemTokens[1] = " + itemTokens[1]);
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
}
else
{ // added fix: If the value is null (the requested field did not appear in the data)
satisfiesQuery = false;
}
++index; // Try to pick up the boolean operators
if (index < (queryTokens.length - 1))
{
if (queryTokens[index].equals("AND")) // Do nothing and keep going
{
if (!satisfiesQuery)
{
break;
}
++index;
item = queryTokens[index];
}
else if (queryTokens[index].equals("OR")) // Assume all OR's occur after all AND's
{
if (satisfiesQuery && (index != 1)) // if we passed the query and it is not the first term
{
break;
}
else
{
++index;
item = queryTokens[index];
satisfiesQuery = true; // reset so that we pick up matches for the next term
}
}
else if (!satisfiesQuery)
{
logger.debug("Does not satisfy the query and no boolean ops next...");
break;
}
}
}
return satisfiesQuery;
}
@SuppressWarnings("unchecked")
public static boolean checkRecordWritableArrayWritable(String uriQuery, MapWritable doc, DataSchema dataSchema)
{
boolean satisfiesQuery = true;
logger.debug("uriQuery = " + uriQuery);
uriQuery = uriQuery.substring(3); // strip the beginning query tag '?q='
logger.debug("uriQuery = " + uriQuery);
if (uriQuery.equals("*"))
{
return true;
}
String[] queryTokens = uriQuery.split("\\+(?=AND)|\\+(?=OR)|\\+(?=[a-z])"); // booleans of the form +AND+, +OR+, don't split on +T0+
int index = 0;
String item;
while (index < queryTokens.length)
{
boolean ignoreCase = false;
item = queryTokens[index];
logger.debug("item = " + item);
String[] itemTokens = item.split(":", 2); // There are two components <field>:<query>
logger.debug("itemTokens[0] = " + itemTokens[0] + " itemTokens[1] = " + itemTokens[1]);
// check for ignore case flag
if (itemTokens[0].endsWith("@"))
{
ignoreCase = true;
logger.debug("ignore case = true");
itemTokens[0] = itemTokens[0].replaceAll("@", ""); // strip flag
logger.debug("itemTokens[0]:" + itemTokens[0]);
}
Object value = doc.get(new Text(itemTokens[0]));
if (value != null) // if the field is not present, a null Writable is returned
{
if (itemTokens[1].startsWith("[")) // Inclusive range query
{
if (value instanceof Text)
{
if (!checkRangeQuery(true, itemTokens[0], itemTokens[1], value.toString(), dataSchema))
{
logger.debug("checkRangeQuery returned false");
satisfiesQuery = false;
}
}
else if (value instanceof WritableArrayWritable)
{
String[] elements = ((WritableArrayWritable) value).toStrings();
boolean oneSatisfied = false;
for (String element : elements)
{
if (checkRangeQuery(true, itemTokens[0], itemTokens[1], element, dataSchema))
{
logger.debug("checkRangeQuery returned true");
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
else if (itemTokens[1].startsWith("{")) // Exclusive range query
{
if (value instanceof Text)
{
if (!checkRangeQuery(false, itemTokens[0], itemTokens[1], value.toString(), dataSchema))
{
logger.debug("checkRangeQuery returned false");
satisfiesQuery = false;
}
}
else if (value instanceof WritableArrayWritable)
{
String[] elements = ((WritableArrayWritable) value).toStrings();
boolean oneSatisfied = false;
for (String element : elements)
{
if (checkRangeQuery(false, itemTokens[0], itemTokens[1], element, dataSchema))
{
logger.debug("checkRangeQuery returned true");
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
else
// Not a range query
{
if (value instanceof Text)
{
String valueString = value.toString();
if (ignoreCase)
{ // Case insensitivity
logger.debug("not a range query; itemstoken1:" + itemTokens[1]);
itemTokens[1] = itemTokens[1].toLowerCase();
valueString = valueString.toLowerCase();
logger.debug("valuestring after:" + valueString);
}
if (itemTokens[1].contains("*") || itemTokens[1].contains("?")) // Wildcard match
{
logger.debug("itemTokens[1] = " + itemTokens[1] + " contains wildcard");
if (!Pattern.matches(wildcardToRegex(itemTokens[1]), valueString))
{
logger.debug("stringValue = " + valueString + " did not satisfy itemTokens[1] = " + itemTokens[1]);
satisfiesQuery = false;
}
logger.debug("stringValue = " + valueString + " did satisfy itemTokens[1] = " + itemTokens[1]);
}
else if (!(valueString).equals(itemTokens[1])) // Single value match
{
logger.debug("We do not have a single value match: stringValue " + valueString + " != itemTokens[1] = " + itemTokens[1]);
satisfiesQuery = false;
}
}
else if (value instanceof WritableArrayWritable)
{
String[] elements = ((WritableArrayWritable) value).toStrings();
logger.debug("elements.size() = " + elements.length);
boolean oneSatisfied = false;
for (String element : elements)
{
if (ignoreCase)
{ // Case insensitivity
itemTokens[1] = itemTokens[1].toLowerCase();
logger.debug("waw: itemtoken1 after:" + itemTokens[1]);
element = element.toLowerCase();
logger.debug("element after:" + element);
}
logger.debug("element: " + element);
if (itemTokens[1].contains("*") || itemTokens[1].contains("?")) // Wildcard match
{
logger.debug("itemTokens[1] = " + itemTokens[1] + " contains wildcard");
if (Pattern.matches(wildcardToRegex(itemTokens[1]), element))
{
logger.debug("stringValue = " + element + " satisfied itemTokens[1] = " + itemTokens[1]);
oneSatisfied = true;
break;
}
}
else if (element.equals(itemTokens[1])) // Single value match
{
logger.debug("We have a single value match: stringValue " + element + " = itemTokens[1] = " + itemTokens[1]);
oneSatisfied = true;
break;
}
}
satisfiesQuery = oneSatisfied;
}
}
}
else
{
satisfiesQuery = false; // add fix - account for case if query field does not exist
}
++index; // Try to pick up the boolean operators
if (index < (queryTokens.length - 1))
{
if (queryTokens[index].equals("AND")) // Do nothing and keep going
{
if (!satisfiesQuery)
{
break;
}
++index;
item = queryTokens[index];
}
else if (queryTokens[index].equals("OR")) // Assume all OR's occur after all AND's
{
if (satisfiesQuery) // if we passed the query and it is not the first term
{
break;
}
else
{
++index;
item = queryTokens[index];
satisfiesQuery = true; // reset so that we pick up matches for the next term
}
}
else if (!satisfiesQuery)
{
logger.debug("Does not satisfy the query and no boolean ops next...");
break;
}
}
}
return satisfiesQuery;
}
/**
* Method to handle ranges queries
*
*/
public static boolean checkRangeQuery(boolean inclusive, String field, String query, String value, DataSchema dataSchema)
{
boolean matches = true;
logger.info("inclusive = " + inclusive + " field = " + field + " query = " + query + " value = " + value);
// Strip the brackets or braces to obtain query form <lower>+TO+<upper>
if (inclusive)
{
query = query.replaceFirst("\\[", "");
query = query.replaceFirst("\\]", "");
}
else
{
query = query.replaceFirst("\\{", "");
query = query.replaceFirst("\\}", "");
}
logger.debug("query = " + query);
// Special case for IPs
if (dataSchema.getPartitionerTypeName(field).equals(IPDataPartitioner.class.getName())) // Doesn't handle arrays of IPs in the value right now...
{
logger.debug("Have IP Field");
String[] ranges = query.split("\\+TO\\+");
logger.info("ranges[0] = " + ranges[0] + " ranges[1] = " + ranges[1]);
if ((!inclusive) && (value.equals(ranges[0]) || value.equals(ranges[1])))
{
logger.debug("inclusive = false and either value.equals(ranges[0]) or value.equals(ranges[1])");
matches = false;
}
else
{
String[] blocksLower = ranges[0].split("\\.");
String[] blocksUpper = ranges[1].split("\\.");
String[] ipValue = value.split("\\.");
int ipBlock = 0;
while (ipBlock < 4)
{
logger.info("ipBlock = " + ipBlock + " ipValue[ipBlock] = " + ipValue[ipBlock] + " blocksLower[ipBlock] = " + blocksLower[ipBlock]
+ " blocksUpper[ipBlock] = " + blocksUpper[ipBlock]);
if (blocksLower[ipBlock].equals(blocksUpper[ipBlock]))
{
logger.info("blocksLower[ipBlock].equals(blocksUpper[ipBlock])");
if (!ipValue[ipBlock].equals(blocksLower[ipBlock]))
{
logger.info("!ipValue[ipBlock].equals(blocksLower[ipBlock]");
matches = false;
}
}
else
{
if (!((Integer.parseInt(blocksLower[ipBlock]) <= Integer.parseInt(ipValue[ipBlock]))
&& (Integer.parseInt(ipValue[ipBlock]) <= Integer.parseInt(blocksUpper[ipBlock]))))
{
logger.info("IP block not within given range");
matches = false;
}
}
++ipBlock;
}
}
}
else if (field.equals("date"))// Special case for ISO8601 dates & Epoch Dates
{
String[] ranges = query.split("\\+TO\\+");
logger.info("query:" + query);
logger.info("value:" + value);
logger.info("ranges[0] = " + ranges[0] + " ranges[1] = " + ranges[1]);
// code to parse epoch time: VacantArmy
if ((EpochDateParser.isEpochDateFormat(ranges[0]) || EpochDateParser.isEpochDateSearchFormat(ranges[0]))
&& (EpochDateParser.isEpochDateFormat(ranges[1]) || EpochDateParser.isEpochDateSearchFormat(ranges[1])))
{
double fromDate = 0;
double toDate = 0;
double valueDate = 0;
long fromSeconds = 0;
long fromMilli = 0;
long toSeconds = 0;
long toMilli = 0;
try
{
fromDate = EpochDateParser.convertSearchDate(ranges[0]);
toDate = EpochDateParser.convertSearchDate(ranges[1]);
valueDate = Double.parseDouble(value);
logger.debug("fromDate:" + fromDate);
logger.debug("toDate:" + toDate);
logger.debug("valueDate:" + valueDate);
// split up seconds & milliseconds...keep? needed??
String[] fromDateArr = ranges[0].split("\\.");
fromSeconds = Integer.parseInt(fromDateArr[0]);
fromMilli = Integer.parseInt(fromDateArr[1]);
String[] toDateArr = ranges[1].split("\\.");
toSeconds = Integer.parseInt(toDateArr[0]);
toMilli = Integer.parseInt(toDateArr[1]);
} catch (Exception e)
{
logger.info(Arrays.toString(e.getStackTrace()));
}
if ((!inclusive) && (fromDate == valueDate || toDate == valueDate))
{
logger.debug("(inclusive == false) && (fromDate == valueDate || toDate == valueDate))");
matches = false;
}
else
{
if (!((fromDate <= valueDate) && (valueDate <= toDate)))
{
logger.debug("valueDate = " + valueDate + " out of range: <" + fromDate + "," + toDate + ">");
matches = false;
}
}
}
else
{ // Special case for ISO8061 dates
long lower = 0;
long upper = 0;
long valueDate = 0;
try
{
lower = ISO8601DateParser.getLongDate(ranges[0]);
upper = ISO8601DateParser.getLongDate(ranges[1]);
valueDate = ISO8601DateParser.getLongDate(value);
} catch (ParseException e)
{
e.printStackTrace();
}
if ((!inclusive) && (lower == valueDate || upper == valueDate))
{
logger.debug("(inclusive == false) && (lower == valueDate || upper == valueDate))");
matches = false;
}
else
{
if (!((lower <= valueDate) && (valueDate <= upper)))
{
logger.debug("valueDate = " + valueDate + " out of range: <" + lower + "," + upper + ">");
matches = false;
}
}
logger.debug("valueDate = " + valueDate + " in range: <" + lower + "," + upper + ">");
}
}
else
// Int
{
String[] ranges = query.split("\\+TO\\+");
// check for ints
// if (ranges[0].matches("\\d+") && ranges[1].matches("\\d+")){ //int range
int lower = Integer.parseInt(ranges[0]);
int upper = Integer.parseInt(ranges[1]);
int valueInt = Integer.parseInt(value);
logger.debug("valueInt = " + valueInt + " lower = " + lower + " upper = " + upper);
if ((!inclusive) && (lower == valueInt || upper == valueInt))
{
logger.debug("(inclusive == false) && (lower == valueInt || upper == valueInt))");
matches = false;
}
else
{
if (!((lower <= valueInt) && (valueInt <= upper)))
{
logger.debug("valueInt = " + valueInt + " out of range: <" + lower + "," + upper + ">");
matches = false;
}
}
logger.debug("valueInt = " + valueInt + " in range: <" + lower + "," + upper + ">");
}
return matches;
}
/**
* Method to convert a URI wildcard query into a java regex
*
*/
public static String wildcardToRegex(String wildcard)
{
StringBuilder s = new StringBuilder(wildcard.length());
for (int i = 0, is = wildcard.length(); i < is; i++)
{
char c = wildcard.charAt(i);
switch (c)
{
case '*':
s.append(".*");
break;
case '?':
s.append(".");
break;
// escape special regexp-characters
case '(':
case ')':
case '[':
case ']':
case '$':
case '^':
case '.':
case '{':
case '}':
case '|':
case '\\':
s.append("\\");
s.append(c);
break;
default:
s.append(c);
break;
}
}
logger.debug("regex = " + s.toString());
return (s.toString());
}
}