package com.turtleplayer.common;
import com.turtleplayer.persistance.framework.filter.*;
import com.turtleplayer.persistance.source.relational.FieldPersistable;
import com.turtleplayer.persistance.source.relational.fieldtype.FieldPersistableAsDouble;
import com.turtleplayer.persistance.source.relational.fieldtype.FieldPersistableAsInteger;
import com.turtleplayer.persistance.source.relational.fieldtype.FieldPersistableAsString;
import com.turtleplayer.persistance.source.relational.fieldtype.FieldVisitor;
import java.util.regex.Pattern;
/**
* TURTLE PLAYER
* <p/>
* Licensed under MIT & GPL
* <p/>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
* OR OTHER DEALINGS IN THE SOFTWARE.
* <p/>
* More Information @ www.turtle-player.co.uk
*
* @author Simon Honegger (Hoene84)
*/
public class MatchFilterVisitor<RESULT, PROJECTION> extends FilterVisitorGenerified<PROJECTION, RESULT, Object, Boolean>
{
private final RESULT instance;
public MatchFilterVisitor(RESULT instance)
{
this.instance = instance;
}
@Override
public Boolean visit(final FieldFilter<PROJECTION, RESULT, Object> fieldFilter,
FieldPersistable<RESULT, Object> field)
{
return field.accept(new FieldVisitor<Boolean, RESULT>()
{
public Boolean visit(FieldPersistableAsString<? super RESULT> field)
{
return matchField((String)fieldFilter.getValue(), field.get(instance), fieldFilter.getOperator());
}
public Boolean visit(FieldPersistableAsDouble<? super RESULT> field)
{
return matchField((Double)fieldFilter.getValue(), field.get(instance), fieldFilter.getOperator());
}
public Boolean visit(FieldPersistableAsInteger<? super RESULT> field)
{
return matchField((Integer)fieldFilter.getValue(), field.get(instance), fieldFilter.getOperator());
}
});
}
public Boolean visit(FilterSet<? super PROJECTION> filterSet)
{
for(Filter<? super PROJECTION> filter : filterSet.getFilters())
{
if(!filter.accept(this))
{
return false;
}
}
return true;
}
public Boolean visit(NotFilter<? super PROJECTION> notFilter)
{
return !notFilter.accept(this);
}
private boolean matchField(String filterValue, String fieldValue, Operator operator){
Boolean nullCompare = matchFieldNull(filterValue, fieldValue, operator);
if(nullCompare != null)
{
return nullCompare;
}
switch (operator)
{
case EQ:
return fieldValue.equals(filterValue);
case NEQ:
return !fieldValue.equals(filterValue);
case GT:
return fieldValue.compareTo(filterValue) > 0;
case LE:
return fieldValue.compareTo(filterValue) <= 0;
case GE:
return fieldValue.compareTo(filterValue) >= 0;
case LIKE:
Pattern p1 = Pattern.compile(filterValue.replaceAll("%", "*"));
return p1.matcher(fieldValue).matches();
case NOT_LIKE:
Pattern p2 = Pattern.compile(filterValue.replaceAll("%", "*"));
return !p2.matcher(fieldValue).matches();
case LT:
return fieldValue.compareTo(filterValue) < 0;
}
throw new RuntimeException("Operator " + operator + " is not supported");
}
private boolean matchField(Double filterValue, Double fieldValue, Operator operator){
Boolean nullCompare = matchFieldNull(filterValue, fieldValue, operator);
if(nullCompare != null)
{
return nullCompare;
}
switch (operator)
{
case EQ:
return fieldValue.equals(filterValue);
case GT:
return fieldValue.compareTo(filterValue) > 0;
case LE:
return fieldValue.compareTo(filterValue) <= 0;
case GE:
return fieldValue.compareTo(filterValue) >= 0;
case LIKE:
return String.valueOf(fieldValue).contains(String.valueOf(filterValue));
case LT:
return fieldValue.compareTo(filterValue) < 0;
case NOT_LIKE:
return !String.valueOf(fieldValue).contains(String.valueOf(filterValue));
case NEQ:
return !fieldValue.equals(filterValue);
}
throw new RuntimeException("Operator " + operator + " is not supported");
}
private boolean matchField(Integer filterValue, Integer fieldValue, Operator operator){
Boolean nullCompare = matchFieldNull(filterValue, fieldValue, operator);
if(nullCompare != null)
{
return nullCompare;
}
switch (operator)
{
case EQ:
return fieldValue.equals(filterValue);
case NEQ:
return !fieldValue.equals(filterValue);
case GT:
return fieldValue.compareTo(filterValue) > 0;
case LE:
return fieldValue.compareTo(filterValue) <= 0;
case GE:
return fieldValue.compareTo(filterValue) >= 0;
case LIKE:
return String.valueOf(fieldValue).contains(String.valueOf(filterValue));
case NOT_LIKE:
return !String.valueOf(fieldValue).contains(String.valueOf(filterValue));
case LT:
return fieldValue.compareTo(filterValue) < 0;
}
throw new RuntimeException("Operator " + operator + " is not supported");
}
/**
* TODO Refactor, seems to be not used, implementation is bullshit
*/
private Boolean matchFieldNull(Object filterValue, Object fieldValue, Operator operator){
if(filterValue != null || fieldValue != null) return null;
switch (operator)
{
case NEQ:
return filterValue != fieldValue;
case EQ:
return filterValue == fieldValue;
case GT:
return filterValue != fieldValue && fieldValue != null;
case LE:
return filterValue == fieldValue || fieldValue == null;
case GE:
return fieldValue == filterValue || fieldValue != null;
case LIKE:
return fieldValue == filterValue || filterValue == null;
case NOT_LIKE:
return fieldValue != filterValue || filterValue == null;
case LT:
return filterValue != fieldValue && fieldValue == null;
}
throw new RuntimeException("Operator " + operator + " is not supported");
}
}