/*
* *************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
* *************************************************************************************
*/
package com.espertech.esper.epl.join.exec.composite;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.epl.join.exec.base.RangeIndexLookupValue;
import com.espertech.esper.epl.join.exec.base.RangeIndexLookupValueEquals;
import com.espertech.esper.epl.join.exec.base.RangeIndexLookupValueRange;
import com.espertech.esper.epl.join.plan.QueryGraphRangeEnum;
import com.espertech.esper.event.EventBeanUtility;
import com.espertech.esper.filter.Range;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
public class CompositeIndexLookupRange implements CompositeIndexLookup {
private final RangeIndexLookupValue lookupValue;
private final Class coercionType;
private CompositeIndexLookup next;
public CompositeIndexLookupRange(RangeIndexLookupValue lookupValue, Class coercionType) {
this.lookupValue = lookupValue;
this.coercionType = coercionType;
}
public void lookup(Map parent, Set<EventBean> result) {
if (lookupValue instanceof RangeIndexLookupValueEquals) {
RangeIndexLookupValueEquals equals = (RangeIndexLookupValueEquals) lookupValue;
Object inner = parent.get(equals.getValue());
if (next == null) {
result.addAll((Set<EventBean>) inner);
}
else {
Map innerMap = (Map) inner;
next.lookup(innerMap, result);
}
return;
}
RangeIndexLookupValueRange lookup = (RangeIndexLookupValueRange) lookupValue;
TreeMap treeMap = (TreeMap) parent;
Object rangeValue = lookup.getValue();
if (lookup.getOperator() == QueryGraphRangeEnum.RANGE_CLOSED) {
Range range = (Range) rangeValue;
lookupRange(result, treeMap, range.getLowEndpoint(), true, range.getHighEndpoint(), true, true);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.RANGE_HALF_OPEN) {
Range range = (Range) rangeValue;
lookupRange(result, treeMap, range.getLowEndpoint(), true, range.getHighEndpoint(), false, true);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.RANGE_HALF_CLOSED) {
Range range = (Range) rangeValue;
lookupRange(result, treeMap, range.getLowEndpoint(), false, range.getHighEndpoint(), true, true);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.RANGE_OPEN) {
Range range = (Range) rangeValue;
lookupRange(result, treeMap, range.getLowEndpoint(), false, range.getHighEndpoint(), false, true);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.NOT_RANGE_CLOSED) {
Range range = (Range) rangeValue;
lookupRangeInverted(result, treeMap, range.getLowEndpoint(), true, range.getHighEndpoint(), true);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.NOT_RANGE_HALF_OPEN) {
Range range = (Range) rangeValue;
lookupRangeInverted(result, treeMap, range.getLowEndpoint(), true, range.getHighEndpoint(), false);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.NOT_RANGE_HALF_CLOSED) {
Range range = (Range) rangeValue;
lookupRangeInverted(result, treeMap, range.getLowEndpoint(), false, range.getHighEndpoint(), true);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.NOT_RANGE_OPEN) {
Range range = (Range) rangeValue;
lookupRangeInverted(result, treeMap, range.getLowEndpoint(), false, range.getHighEndpoint(), false);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.GREATER) {
lookupGreater(result, treeMap, rangeValue);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.GREATER_OR_EQUAL) {
lookupGreaterEqual(result, treeMap, rangeValue);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.LESS) {
lookupLess(result, treeMap, rangeValue);
}
else if (lookup.getOperator() == QueryGraphRangeEnum.LESS_OR_EQUAL) {
lookupLessEqual(result, treeMap, rangeValue);
}
else {
throw new IllegalArgumentException("Unrecognized operator '" + lookup.getOperator() + "'");
}
}
public void lookupRange(Set<EventBean> result, TreeMap propertyIndex, Object keyStart, boolean includeStart, Object keyEnd, boolean includeEnd, boolean allowRangeReversal) {
if (keyStart == null || keyEnd == null) {
return;
}
keyStart = coerce(keyStart);
keyEnd = coerce(keyEnd);
SortedMap<Object,Object> submap;
try {
submap = propertyIndex.subMap(keyStart, includeStart, keyEnd, includeEnd);
}
catch (IllegalArgumentException ex) {
if (allowRangeReversal) {
submap = propertyIndex.subMap(keyEnd, includeStart, keyStart, includeEnd);
}
else {
return;
}
}
normalize(result, submap);
}
public void lookupRangeInverted(Set<EventBean> result, TreeMap propertyIndex, Object keyStart, boolean includeStart, Object keyEnd, boolean includeEnd) {
if (keyStart == null || keyEnd == null) {
return;
}
keyStart = coerce(keyStart);
keyEnd = coerce(keyEnd);
SortedMap<Object,Object> submapOne = propertyIndex.headMap(keyStart, !includeStart);
SortedMap<Object,Object> submapTwo = propertyIndex.tailMap(keyEnd, !includeEnd);
normalize(result, submapOne, submapTwo);
}
public void lookupLess(Set<EventBean> result, TreeMap propertyIndex, Object keyStart) {
if (keyStart == null) {
return;
}
keyStart = coerce(keyStart);
normalize(result, propertyIndex.headMap(keyStart));
}
public void lookupLessEqual(Set<EventBean> result, TreeMap propertyIndex, Object keyStart) {
if (keyStart == null) {
return;
}
keyStart = coerce(keyStart);
normalize(result, propertyIndex.headMap(keyStart, true));
}
public void lookupGreaterEqual(Set<EventBean> result, TreeMap propertyIndex, Object keyStart) {
if (keyStart == null) {
return;
}
keyStart = coerce(keyStart);
normalize(result, propertyIndex.tailMap(keyStart));
}
public void lookupGreater(Set<EventBean> result, TreeMap propertyIndex, Object keyStart) {
if (keyStart == null) {
return;
}
keyStart = coerce(keyStart);
normalize(result, propertyIndex.tailMap(keyStart, false));
}
private Object coerce(Object key) {
return EventBeanUtility.coerce(key, coercionType);
}
private void normalize(Set<EventBean> result, Map<Object, Object> submap) {
if (submap.size() == 0) {
return;
}
if (next == null) {
for (Map.Entry<Object, Object> entry : submap.entrySet()) {
Set<EventBean> set = (Set<EventBean>) entry.getValue();
result.addAll(set);
}
}
else {
for (Map.Entry<Object,Object> entry : submap.entrySet()) {
TreeMap index = (TreeMap) entry.getValue();
next.lookup(index, result);
}
}
}
private void normalize(Set<EventBean> result, SortedMap<Object,Object> submapOne, SortedMap<Object,Object> submapTwo) {
normalize(result, submapTwo);
normalize(result, submapOne);
}
public void setNext(CompositeIndexLookup next) {
this.next = next;
}
}