/*
* Copyright 2014 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.dashbuilder.dataset.engine.filter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dashbuilder.dataset.filter.CoreFunctionFilter;
import org.dashbuilder.dataset.filter.CoreFunctionType;
import org.dashbuilder.dataset.date.TimeFrame;
public class CoreFunction extends DataSetFunction {
private CoreFunctionFilter coreFunctionFilter = null;
public CoreFunction(DataSetFilterContext ctx, CoreFunctionFilter coreFunctionFilter) {
super(ctx, coreFunctionFilter);
this.coreFunctionFilter = coreFunctionFilter;
}
public Comparable getCurrentValue() {
return (Comparable) getDataColumn().getValues().get(getContext().getCurrentRow());
}
public Comparable getParameter(int index) {
if (index >= coreFunctionFilter.getParameters().size()) {
return null;
}
return (Comparable) coreFunctionFilter.getParameters().get(index);
}
public List<Comparable> getParameters() {
return coreFunctionFilter.getParameters();
}
public boolean pass() {
CoreFunctionType type = coreFunctionFilter.getType();
if (CoreFunctionType.IS_NULL.equals(type)) {
return isNull(getCurrentValue());
}
if (CoreFunctionType.NOT_NULL.equals(type)) {
return isNotNull(getCurrentValue());
}
if (CoreFunctionType.EQUALS_TO.equals(type)) {
return isEqualsTo(getCurrentValue());
}
if (CoreFunctionType.NOT_EQUALS_TO.equals(type)) {
return isNotEqualsTo(getCurrentValue());
}
if (CoreFunctionType.LIKE_TO.equals(type)) {
return isLikeTo(getCurrentValue());
}
if (CoreFunctionType.LOWER_THAN.equals(type)) {
return isLowerThan(getCurrentValue());
}
if (CoreFunctionType.LOWER_OR_EQUALS_TO.equals(type)) {
return isLowerThanOrEqualsTo(getCurrentValue());
}
if (CoreFunctionType.GREATER_THAN.equals(type)) {
return isGreaterThan(getCurrentValue());
}
if (CoreFunctionType.GREATER_OR_EQUALS_TO.equals(type)) {
return isGreaterThanOrEqualsTo(getCurrentValue());
}
if (CoreFunctionType.BETWEEN.equals(type)) {
return isBetween(getCurrentValue());
}
if (CoreFunctionType.TIME_FRAME.equals(type)) {
return timeFrame(getCurrentValue());
}
if (CoreFunctionType.IN.equals(type)) {
return isEqualsTo(getCurrentValue());
}
if (CoreFunctionType.NOT_IN.equals(type)) {
return isNotEqualsTo(getCurrentValue());
}
throw new IllegalArgumentException("Core function type not supported: " + type);
}
public boolean isNull(Comparable value) {
return value == null;
}
public boolean isNotNull(Comparable value) {
return !isNull(value);
}
public boolean compare(Comparable c1, Comparable c2) {
if (c1 == null && c2 == null) {
return true;
}
if (c1 != null && c2 != null) {
if ((c1 instanceof Number) && (c2 instanceof Number)) {
return ((Number) c1).doubleValue() == ((Number) c2).doubleValue();
}
return c1.toString().equals(c2.toString());
}
return false;
}
public boolean isEqualsTo(Comparable value) {
// No parameters to compare => return true
if (getParameters().isEmpty()) {
return true;
}
// At least one parameter match is required
for (Comparable param : getParameters()) {
if (compare(param, value)) {
return true;
}
}
return false;
}
public boolean isNotEqualsTo(Comparable value) {
// No parameters to compare => return true
if (getParameters().isEmpty()) {
return true;
}
return !isEqualsTo(value);
}
/**
* <p>The <code>LIKE_TO</code> operator is intended to emulate the SQL like operator.It's used to search for a specified pattern in a data set's column.</p>
* <p>Allowed wildcards are:</p>
* <ul>
* <li><code>_</code> - A substitute for a single character.</li>
* <li><code>%</code> - A substitute for zero or more characters.</li>
* <li><code>[charlist]</code> - Sets and ranges of characters to match.</li>
* <li><code>[^charlist]</code> - Matches only a character NOT specified within the brackets.</li>
* </ul>
*
* <p>The call <code>getParameter(0)</code> returns the given user's input pattern used for searching.</p>
*
* <p>The implementation is supported for TEXT or LABEL column types and it's case sensitive or
* unsensitive depending on the boolean value returned by getParameter(1).</p>
*
* @param value The existing data set column's value at a given row.
* @return If the string on current data set's column is like (as the SQL operator) the given user's pattern.
*/
public boolean isLikeTo(Comparable value) {
if (value == null) {
return false;
}
final Comparable param0 = getParameter(0);
if (param0 == null) {
return false;
}
// Case sensitive parameter
final Boolean caseSensitive = getParameter(1) != null ? Boolean.parseBoolean(getParameter(1).toString()) : true;
String pattern = caseSensitive ? param0.toString() : param0.toString().toLowerCase();
String strValue = caseSensitive ? value.toString() : value.toString().toLowerCase();
// Replace the user's wilcards that come from the UI request for valid regular expression patterns.
pattern = pattern.replace(".", "\\."); // "\\" is escaped to "\"
pattern = pattern.replace("%", ".*");
pattern = pattern.replace("_", ".");
// Perform the regexp match operation.
return strValue.matches(pattern);
}
public boolean isLowerThan(Comparable value) {
return !isGreaterThanOrEqualsTo(value);
}
public boolean isLowerThanOrEqualsTo(Comparable value) {
return !isGreaterThan(value);
}
public boolean isGreaterThan(Comparable value) {
if (value == null) {
return false;
}
Comparable ref = getParameter(0);
return ref == null || value.compareTo(ref) == 1;
}
public boolean isGreaterThanOrEqualsTo(Comparable value) {
Comparable ref = getParameter(0);
if (ref == null) {
return true;
} else {
return value != null && value.compareTo(ref) != -1;
}
}
public boolean isBetween(Comparable value) {
Comparable low = getParameter(0);
Comparable high = getParameter(1);
if (value == null) {
return low == null;
}
if (low != null && value.compareTo(low) == -1) {
return false;
}
if (high != null && value.compareTo(high) == 1) {
return false;
}
return true;
}
Map<String, TimeFrameLimits> _timeFrameExprCache = new HashMap<String, TimeFrameLimits>();
public boolean timeFrame(Comparable value) {
String timeFrameExpr = getParameter(0).toString();
if (timeFrameExpr == null || value == null) {
return false;
}
if (!(value instanceof Date)) {
return false;
}
Date target = (Date) value;
TimeFrameLimits timeFrameLimits = _timeFrameExprCache.get(timeFrameExpr);
if (timeFrameLimits == null) {
TimeFrame timeFrame = TimeFrame.parse(getParameter(0).toString());
_timeFrameExprCache.put(timeFrameExpr, timeFrameLimits = new TimeFrameLimits(timeFrame));
}
if (target.before(timeFrameLimits.from)) return false;
if (target.after(timeFrameLimits.to)) return false;
return true;
}
public class TimeFrameLimits {
Date from = null;
Date to = null;
public TimeFrameLimits(TimeFrame timeFrame) {
from = timeFrame.getFrom().getTimeInstant();
to = timeFrame.getTo().getTimeInstant();
}
}
}