/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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.filter;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
/**
* This class holds a list of indizes storing filter constants in {@link FilterParamIndexBase} nodes
* and a set of {@link FilterHandle}.
* An instance of this class represents a leaf-node (no indizes stored, just filter callbacks)
* but can also be non-leaf (some indizes exist) in a filter evaluation tree.
* Events are evaluated by asking each of the indizes to evaluate the event and by
* adding any filter callbacks in this node to the "matches" list of callbacks.
*/
public final class FilterHandleSetNode implements EventEvaluator {
private final ReadWriteLock nodeRWLock;
private final Set<FilterHandle> callbackSet;
private final List<FilterParamIndexBase> indizes;
public FilterHandleSetNode(ReadWriteLock nodeRWLock) {
this.nodeRWLock = nodeRWLock;
callbackSet = new LinkedHashSet<FilterHandle>();
indizes = new LinkedList<FilterParamIndexBase>();
}
/**
* Returns an indication of whether there are any callbacks or index nodes at all in this set.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @return true if there are neither indizes nor filter callbacks stored, false if either exist.
*/
public boolean isEmpty() {
return callbackSet.isEmpty() && indizes.isEmpty();
}
/**
* Returns the number of filter callbacks stored.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @return number of filter callbacks stored
*/
public int getFilterCallbackCount() {
return callbackSet.size();
}
/**
* Returns to lock to use for making changes to the filter callback or inzides collections stored by this node.
*
* @return lock to use in multithreaded environment
*/
public final ReadWriteLock getNodeRWLock() {
return nodeRWLock;
}
/**
* Returns list of indexes - not returning an iterator. Client classes should not change this collection.
*
* @return list of indizes
*/
public List<FilterParamIndexBase> getIndizes() {
return indizes;
}
/**
* Evaluate an event by asking each index to match the event. Any filter callbacks at this node automatically
* match the event and do not need to be further evaluated, and are thus added to the "matches" list of callbacks.
* NOTE: This client should not use the lock before calling this method.
*
* @param theEvent is the event wrapper supplying the event property values
* @param matches is the list of callbacks to add to for any matches found
*/
public final void matchEvent(EventBean theEvent, Collection<FilterHandle> matches) {
nodeRWLock.readLock().lock();
try {
if (InstrumentationHelper.ENABLED) {
if (!indizes.isEmpty()) {
InstrumentationHelper.get().qFilterHandleSetIndexes(indizes);
}
}
// Ask each of the indizes to match against the attribute values
for (FilterParamIndexBase index : indizes) {
index.matchEvent(theEvent, matches);
}
if (InstrumentationHelper.ENABLED) {
if (!indizes.isEmpty()) {
InstrumentationHelper.get().aFilterHandleSetIndexes();
}
}
if (InstrumentationHelper.ENABLED) {
if (!callbackSet.isEmpty()) {
InstrumentationHelper.get().qaFilterHandleSetCallbacks(callbackSet);
}
}
// Add each filter callback stored in this node to the matching list
for (FilterHandle filterCallback : callbackSet) {
matches.add(filterCallback);
}
} finally {
nodeRWLock.readLock().unlock();
}
}
/**
* Returns an indication whether the filter callback exists in this node.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @param filterCallback is the filter callback to check for
* @return true if callback found, false if not
*/
public boolean contains(FilterHandle filterCallback) {
return callbackSet.contains(filterCallback);
}
/**
* Add an index. The same index can be added twice - there is no checking done.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @param index - index to add
*/
public final void add(FilterParamIndexBase index) {
indizes.add(index);
}
/**
* Remove an index, returning true if it was found and removed or false if not in collection.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @param index is the index to remove
* @return true if found, false if not existing
*/
public final boolean remove(FilterParamIndexBase index) {
return indizes.remove(index);
}
/**
* Add a filter callback. The filter callback set allows adding the same callback twice with no effect.
* If a client to the class needs to check that the callback already existed, the contains method does that.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @param filterCallback is the callback to add
*/
public final void add(FilterHandle filterCallback) {
callbackSet.add(filterCallback);
}
/**
* Remove a filter callback, returning true if it was found and removed or false if not in collection.
* NOTE: the client to this method must use the read-write lock of this object to lock, if required by the client
* code.
*
* @param filterCallback is the callback to remove
* @return true if found, false if not existing
*/
public final boolean remove(FilterHandle filterCallback) {
return callbackSet.remove(filterCallback);
}
public Set<FilterHandle> getCallbackSet() {
return callbackSet;
}
}