- // if propertyName found for this filter,
- PropertyMap::const_iterator propIter = Properties.find(propertyName);
- if ( propIter != Properties.end() ) {
- const PropertyFilterValue& filterValue = (*propIter).second;
-
- // check
- switch ( Type ) {
- case ( PropertyFilter::EXACT ) : return filterValue.check(query);
- case ( PropertyFilter::NOT ) : return !filterValue.check(query);
- case ( PropertyFilter::AND ) :
- case ( PropertyFilter::OR ) : BAMTOOLS_ASSERT_MESSAGE(false, "Cannot use a binary compare operator on 1 value");
- default : BAMTOOLS_ASSERT_UNREACHABLE;
- }
- return false; // unreachable
+ // return result of querying against filter rules
+ return evaluateFilterRules(query);
+}
+
+// returns list of property names that are 'enabled' ( only those touched by setProperty() )
+template<typename FilterChecker>
+inline const std::vector<std::string> FilterEngine<FilterChecker>::enabledPropertyNames(void) {
+ // initialize stringlist
+ std::vector<std::string> names;
+ names.reserve(m_properties.size());
+ // iterate over all properties, appending if enabled
+ std::vector<Property>::const_iterator propIter = m_properties.begin();
+ std::vector<Property>::const_iterator propEnd = m_properties.end();
+ for ( ; propIter != propEnd; ++propIter )
+ if ( (*propIter).IsEnabled )
+ names.push_back( (*propIter).Name );
+ // return stringlist
+ return names;
+}
+
+// evaluates postfix rule queue - with each filter as an operand, AND|OR|NOT as operators
+template<class FilterChecker> template<typename T>
+bool FilterEngine<FilterChecker>::evaluateFilterRules(const T& query) {
+
+ // build ruleQueue if not done before
+ if ( !m_isRuleQueueGenerated )
+ buildRuleQueue();
+
+ std::stack<bool> resultStack;
+ FilterMap::const_iterator filterIter;
+ std::queue<std::string> ruleQueueCopy = m_ruleQueue;
+ while ( !ruleQueueCopy.empty() ) {
+ const std::string& token = ruleQueueCopy.front();
+
+ // token is NOT_OPERATOR
+ if ( token == FilterEngine<FilterChecker>::NOT_OPERATOR ) {
+ BAMTOOLS_ASSERT_MESSAGE( !resultStack.empty(), "Empty result stack - cannot apply operator: !" );
+ resultStack.top() = !resultStack.top();
+ }
+
+ // token is AND_OPERATOR
+ else if ( token == FilterEngine<FilterChecker>::AND_OPERATOR ) {
+ BAMTOOLS_ASSERT_MESSAGE( resultStack.size() >= 2 , "Not enough operands - cannot apply operator: &" );
+ bool topResult = resultStack.top();
+ resultStack.pop();
+ resultStack.top() &= topResult;
+ }
+
+ // token is OR_OPERATOR
+ else if ( token == FilterEngine<FilterChecker>::OR_OPERATOR ) {
+ BAMTOOLS_ASSERT_MESSAGE( resultStack.size() >= 2 , "Not enough operands - cannot apply operator: |" );
+ bool topResult = resultStack.top();
+ resultStack.pop();
+ resultStack.top() |= topResult;
+ }
+
+ // token is an operand
+ else {
+ // look up PropertyFilter that matches this token
+ filterIter = m_filters.find(token);
+ BAMTOOLS_ASSERT_MESSAGE( (filterIter != m_filters.end() ), "Filter mentioned in rule, not found in FilterEngine" );
+ const PropertyFilter& filter = (*filterIter).second;
+ bool result = m_checker.check(filter, query);
+ resultStack.push( result );
+ }
+
+ // pop token from ruleQueue
+ ruleQueueCopy.pop();