/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.activemq.store.kahadb.disk.index; import java.util.List; /** * Interface used to selectively visit the entries in a BTree. * * @param <Key> * @param <Value> */ public interface BTreeVisitor<Key,Value> { /** * Do you want to visit the range of BTree entries between the first and and second key? * * @param first if null indicates the range of values before the second key. * @param second if null indicates the range of values after the first key. * @return true if you want to visit the values between the first and second key. */ boolean isInterestedInKeysBetween(Key first, Key second); /** * The keys and values of a BTree leaf node. * * @param keys * @param values */ void visit(List<Key> keys, List<Value> values); public interface Predicate<Key> { boolean isInterestedInKeysBetween(Key first, Key second); boolean isInterestedInKey(Key key); } abstract class PredicateVisitor<Key, Value> implements BTreeVisitor<Key, Value>, Predicate<Key> { public void visit(List<Key> keys, List<Value> values) { for( int i=0; i < keys.size(); i++) { Key key = keys.get(i); if( isInterestedInKey(key) ) { matched(key, values.get(i)); } } } protected void matched(Key key, Value value) { } } class OrVisitor<Key, Value> extends PredicateVisitor<Key, Value> { private final List<Predicate<Key>> conditions; public OrVisitor(List<Predicate<Key>> conditions) { this.conditions = conditions; } public boolean isInterestedInKeysBetween(Key first, Key second) { for (Predicate<Key> condition : conditions) { if( condition.isInterestedInKeysBetween(first, second) ) { return true; } } return false; } public boolean isInterestedInKey(Key key) { for (Predicate<Key> condition : conditions) { if( condition.isInterestedInKey(key) ) { return true; } } return false; } @Override public String toString() { StringBuilder sb = new StringBuilder(); boolean first=true; for (Predicate<Key> condition : conditions) { if( !first ) { sb.append(" OR "); } first=false; sb.append("("); sb.append(condition); sb.append(")"); } return sb.toString(); } } class AndVisitor<Key, Value> extends PredicateVisitor<Key, Value> { private final List<Predicate<Key>> conditions; public AndVisitor(List<Predicate<Key>> conditions) { this.conditions = conditions; } public boolean isInterestedInKeysBetween(Key first, Key second) { for (Predicate<Key> condition : conditions) { if( !condition.isInterestedInKeysBetween(first, second) ) { return false; } } return true; } public boolean isInterestedInKey(Key key) { for (Predicate<Key> condition : conditions) { if( !condition.isInterestedInKey(key) ) { return false; } } return true; } @Override public String toString() { StringBuilder sb = new StringBuilder(); boolean first=true; for (Predicate<Key> condition : conditions) { if( !first ) { sb.append(" AND "); } first=false; sb.append("("); sb.append(condition); sb.append(")"); } return sb.toString(); } } class BetweenVisitor<Key extends Comparable<Key>, Value> extends PredicateVisitor<Key, Value> { private final Key first; private final Key last; public BetweenVisitor(Key first, Key last) { this.first = first; this.last = last; } public boolean isInterestedInKeysBetween(Key first, Key second) { return (second==null || second.compareTo(this.first)>=0) && (first==null || first.compareTo(last)<0); } public boolean isInterestedInKey(Key key) { return key.compareTo(first) >=0 && key.compareTo(last) <0; } @Override public String toString() { return first+" >= key < "+last; } } class GTVisitor<Key extends Comparable<Key>, Value> extends PredicateVisitor<Key, Value> { final private Key value; public GTVisitor(Key value) { this.value = value; } public boolean isInterestedInKeysBetween(Key first, Key second) { return second==null || second.compareTo(value)>0; } public boolean isInterestedInKey(Key key) { return key.compareTo(value)>0; } @Override public String toString() { return "key > "+ value; } } class GTEVisitor<Key extends Comparable<Key>, Value> extends PredicateVisitor<Key, Value> { final private Key value; public GTEVisitor(Key value) { this.value = value; } public boolean isInterestedInKeysBetween(Key first, Key second) { return second==null || second.compareTo(value)>=0; } public boolean isInterestedInKey(Key key) { return key.compareTo(value)>=0; } @Override public String toString() { return "key >= "+ value; } } class LTVisitor<Key extends Comparable<Key>, Value> extends PredicateVisitor<Key, Value> { final private Key value; public LTVisitor(Key value) { this.value = value; } public boolean isInterestedInKeysBetween(Key first, Key second) { return first==null || first.compareTo(value)<0; } public boolean isInterestedInKey(Key key) { return key.compareTo(value)<0; } @Override public String toString() { return "key < "+ value; } } class LTEVisitor<Key extends Comparable<Key>, Value> extends PredicateVisitor<Key, Value> { final private Key value; public LTEVisitor(Key value) { this.value = value; } public boolean isInterestedInKeysBetween(Key first, Key second) { return first==null || first.compareTo(value)<=0; } public boolean isInterestedInKey(Key key) { return key.compareTo(value)<=0; } @Override public String toString() { return "key <= "+ value; } } }