001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.trie; 018 019import java.io.Serializable; 020import java.util.Comparator; 021 022import org.apache.commons.collections4.Trie; 023 024/** 025 * Defines the interface to analyze {@link Trie Trie} keys on a bit level. 026 * {@link KeyAnalyzer}'s methods return the length of the key in bits, whether or not a bit is set, 027 * and bits per element in the key. 028 * <p> 029 * Additionally, a method determines if a key is a prefix of another 030 * key and returns the bit index where one key is different from another 031 * key (if the key and found key are equal than the return value is 032 * {@link #EQUAL_BIT_KEY}). 033 * </p> 034 * 035 * @param <K> The type of objects that may be compared by this analyzer 036 * @since 4.0 037 */ 038public abstract class KeyAnalyzer<K> implements Comparator<K>, Serializable { 039 040 /** Serialization version */ 041 private static final long serialVersionUID = -20497563720380683L; 042 043 /** 044 * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} 045 * if key's bits are all 0. 046 */ 047 public static final int NULL_BIT_KEY = -1; 048 049 /** 050 * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} if key and found key are equal. 051 * This is a very specific case and shouldn't happen on a regular basis. 052 */ 053 public static final int EQUAL_BIT_KEY = -2; 054 055 /** 056 * Used to test a {@code bitIndex} in {@link #isOutOfBoundsIndex(int)}. 057 */ 058 public static final int OUT_OF_BOUNDS_BIT_KEY = -3; 059 060 /** 061 * Returns true if bitIndex is a {@link KeyAnalyzer#EQUAL_BIT_KEY}. 062 */ 063 static boolean isEqualBitKey(final int bitIndex) { 064 return bitIndex == EQUAL_BIT_KEY; 065 } 066 067 /** 068 * Returns true if bitIndex is a {@link KeyAnalyzer#NULL_BIT_KEY}. 069 */ 070 static boolean isNullBitKey(final int bitIndex) { 071 return bitIndex == NULL_BIT_KEY; 072 } 073 074 /** 075 * Returns true if bitIndex is a {@link KeyAnalyzer#OUT_OF_BOUNDS_BIT_KEY}. 076 */ 077 static boolean isOutOfBoundsIndex(final int bitIndex) { 078 return bitIndex == OUT_OF_BOUNDS_BIT_KEY; 079 } 080 081 /** 082 * Returns true if the given bitIndex is valid. 083 * Indices are considered valid if they're between 0 and {@link Integer#MAX_VALUE} 084 */ 085 static boolean isValidBitIndex(final int bitIndex) { 086 return bitIndex >= 0; 087 } 088 089 /** 090 * Constructs a new instance. 091 */ 092 public KeyAnalyzer() { 093 // empty 094 } 095 096 /** 097 * Returns the n-th different bit between key and other. This starts the comparison in 098 * key at 'offsetInBits' and goes for 'lengthInBits' bits, and compares to the other key starting 099 * at 'otherOffsetInBits' and going for 'otherLengthInBits' bits. 100 * 101 * @param key The key to use 102 * @param offsetInBits The bit offset in the key 103 * @param lengthInBits The maximum key length in bits to use 104 * @param other The other key to use 105 * @param otherOffsetInBits The bit offset in the other key 106 * @param otherLengthInBits The maximum key length in bits for the other key 107 * @return The bit index where the key and other first differ 108 */ 109 public abstract int bitIndex(K key, int offsetInBits, int lengthInBits, 110 K other, int otherOffsetInBits, int otherLengthInBits); 111 112 /** 113 * Returns the number of bits per element in the key. 114 * This is only useful for variable-length keys, such as Strings. 115 * 116 * @return The number of bits per element 117 */ 118 public abstract int bitsPerElement(); 119 120 @Override 121 @SuppressWarnings("unchecked") 122 public int compare(final K o1, final K o2) { 123 if (o1 == null) { 124 return o2 == null ? 0 : -1; 125 } 126 if (o2 == null) { 127 return 1; 128 } 129 130 return ((Comparable<K>) o1).compareTo(o2); 131 } 132 133 /** 134 * Returns whether or not a bit is set. 135 * 136 * @param key The key to check, may not be null 137 * @param bitIndex The bit index to check 138 * @param lengthInBits The maximum key length in bits to check 139 * @return {@code true} if the bit is set in the given key and 140 * {@code bitIndex} < {@code lengthInBits}, {@code false} otherwise. 141 */ 142 public abstract boolean isBitSet(K key, int bitIndex, int lengthInBits); 143 144 /** 145 * Determines whether or not the given prefix (from offset to length) is a prefix of the given key. 146 * 147 * @param prefix The prefix to check 148 * @param offsetInBits The bit offset in the key 149 * @param lengthInBits The maximum key length in bits to use 150 * @param key The key to check 151 * @return {@code true} if this is a valid prefix for the given key 152 */ 153 public abstract boolean isPrefix(K prefix, int offsetInBits, int lengthInBits, K key); 154 155 /** 156 * Returns the length of the Key in bits. 157 * 158 * @param key The key 159 * @return The bit length of the key 160 */ 161 public abstract int lengthInBits(K key); 162 163}