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 * http://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 022/** 023 * Defines the interface to analyze {@link org.apache.commons.collections4.Trie Trie} keys on a bit level. 024 * {@link KeyAnalyzer}'s methods return the length of the key in bits, whether or not a bit is set, 025 * and bits per element in the key. 026 * <p> 027 * Additionally, a method determines if a key is a prefix of another 028 * key and returns the bit index where one key is different from another 029 * key (if the key and found key are equal than the return value is 030 * {@link #EQUAL_BIT_KEY}). 031 * </p> 032 * 033 * @param <K> the type of objects that may be compared by this analyzer 034 * @since 4.0 035 */ 036public abstract class KeyAnalyzer<K> implements Comparator<K>, Serializable { 037 038 /** Serialization version */ 039 private static final long serialVersionUID = -20497563720380683L; 040 041 /** 042 * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} 043 * if key's bits are all 0. 044 */ 045 public static final int NULL_BIT_KEY = -1; 046 047 /** 048 * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} if key and found key are equal. 049 * This is a very specific case and shouldn't happen on a regular basis. 050 */ 051 public static final int EQUAL_BIT_KEY = -2; 052 053 /** 054 * Used to test a {@code bitIndex} in {@link #isOutOfBoundsIndex(int)}. 055 */ 056 public static final int OUT_OF_BOUNDS_BIT_KEY = -3; 057 058 /** 059 * Returns true if bitIndex is a {@link KeyAnalyzer#EQUAL_BIT_KEY}. 060 */ 061 static boolean isEqualBitKey(final int bitIndex) { 062 return bitIndex == EQUAL_BIT_KEY; 063 } 064 065 /** 066 * Returns true if bitIndex is a {@link KeyAnalyzer#NULL_BIT_KEY}. 067 */ 068 static boolean isNullBitKey(final int bitIndex) { 069 return bitIndex == NULL_BIT_KEY; 070 } 071 072 /** 073 * Returns true if bitIndex is a {@link KeyAnalyzer#OUT_OF_BOUNDS_BIT_KEY}. 074 */ 075 static boolean isOutOfBoundsIndex(final int bitIndex) { 076 return bitIndex == OUT_OF_BOUNDS_BIT_KEY; 077 } 078 079 /** 080 * Returns true if the given bitIndex is valid. 081 * Indices are considered valid if they're between 0 and {@link Integer#MAX_VALUE} 082 */ 083 static boolean isValidBitIndex(final int bitIndex) { 084 return bitIndex >= 0; 085 } 086 087 /** 088 * Constructs a new instance. 089 */ 090 public KeyAnalyzer() { 091 // empty 092 } 093 094 /** 095 * Returns the n-th different bit between key and other. This starts the comparison in 096 * key at 'offsetInBits' and goes for 'lengthInBits' bits, and compares to the other key starting 097 * at 'otherOffsetInBits' and going for 'otherLengthInBits' bits. 098 * 099 * @param key the key to use 100 * @param offsetInBits the bit offset in the key 101 * @param lengthInBits the maximum key length in bits to use 102 * @param other the other key to use 103 * @param otherOffsetInBits the bit offset in the other key 104 * @param otherLengthInBits the maximum key length in bits for the other key 105 * @return the bit index where the key and other first differ 106 */ 107 public abstract int bitIndex(K key, int offsetInBits, int lengthInBits, 108 K other, int otherOffsetInBits, int otherLengthInBits); 109 110 /** 111 * Returns the number of bits per element in the key. 112 * This is only useful for variable-length keys, such as Strings. 113 * 114 * @return the number of bits per element 115 */ 116 public abstract int bitsPerElement(); 117 118 @Override 119 @SuppressWarnings("unchecked") 120 public int compare(final K o1, final K o2) { 121 if (o1 == null) { 122 return o2 == null ? 0 : -1; 123 } 124 if (o2 == null) { 125 return 1; 126 } 127 128 return ((Comparable<K>) o1).compareTo(o2); 129 } 130 131 /** 132 * Returns whether or not a bit is set. 133 * 134 * @param key the key to check, may not be null 135 * @param bitIndex the bit index to check 136 * @param lengthInBits the maximum key length in bits to check 137 * @return {@code true} if the bit is set in the given key and 138 * {@code bitIndex} < {@code lengthInBits}, {@code false} otherwise. 139 */ 140 public abstract boolean isBitSet(K key, int bitIndex, int lengthInBits); 141 142 /** 143 * Determines whether or not the given prefix (from offset to length) is a prefix of the given key. 144 * 145 * @param prefix the prefix to check 146 * @param offsetInBits the bit offset in the key 147 * @param lengthInBits the maximum key length in bits to use 148 * @param key the key to check 149 * @return {@code true} if this is a valid prefix for the given key 150 */ 151 public abstract boolean isPrefix(K prefix, int offsetInBits, int lengthInBits, K key); 152 153 /** 154 * Returns the length of the Key in bits. 155 * 156 * @param key the key 157 * @return the bit length of the key 158 */ 159 public abstract int lengthInBits(K key); 160 161}