001/** 002 * The MIT License (MIT) 003 * 004 * Copyright (c) 2018 nobark (tools4j), Marco Terzer, Anton Anufriev 005 * 006 * Permission is hereby granted, free of charge, to any person obtaining a copy 007 * of this software and associated documentation files (the "Software"), to deal 008 * in the Software without restriction, including without limitation the rights 009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 010 * copies of the Software, and to permit persons to whom the Software is 011 * furnished to do so, subject to the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be included in all 014 * copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 022 * SOFTWARE. 023 */ 024package org.tools4j.nobark.queue; 025 026import java.util.Arrays; 027import java.util.List; 028import java.util.Map; 029import java.util.Queue; 030import java.util.function.Supplier; 031 032/** 033 * Builder for the different types of conflation queues serving as alternative to the queue constructors; a builder is 034 * returned by the static methods of this interface. 035 * 036 * @param <K> the type of the conflation key 037 * @param <V> the type of elements in the queue 038 */ 039public interface ConflationQueueBuilder<K,V> { 040 041 /** 042 * Creates an initial builder; use this method only when conflation keys are not known in advance 043 * 044 * @param <K> the type of the conflation key 045 * @param <V> the type of elements in the queue 046 * @return a new builder 047 */ 048 static <K,V> ConflationQueueBuilder<K,V> builder() { 049 return new ConflationQueueBuilderImpl.DefaultBuilder<>(); 050 } 051 052 /** 053 * Creates an initial builder; use this method only when conflation keys are not known in advance. 054 * 055 * @param keyType the type of the conflation key, used only to infer the generic type of the builder 056 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 057 * @param <K> the type of the conflation key 058 * @param <V> the type of elements in the queue 059 * @return a new builder 060 */ 061 static <K,V> ConflationQueueBuilder<K,V> builder(@SuppressWarnings("unused") final Class<K> keyType, 062 @SuppressWarnings("unused") final Class<V> valueType) { 063 return new ConflationQueueBuilderImpl.DefaultBuilder<>(); 064 } 065 066 /** 067 * Creates an initial builder; use this method only when conflation keys are not known in advance. If multiple 068 * producers are used, the map returned by the given map factory should be thread-safe. 069 * 070 * @param entryMapFactory the factory to create the map that manages entries per conflation key 071 * @param <K> the type of the conflation key 072 * @param <V> the type of elements in the queue 073 * @return a new builder 074 */ 075 static <K,V> ConflationQueueBuilder<K,V> builder(final Supplier<? extends Map<Object,Object>> entryMapFactory) { 076 return new ConflationQueueBuilderImpl.EntryMapFactoryBuilder<>(entryMapFactory); 077 } 078 079 /** 080 * Creates an initial builder; use this method only when conflation keys are not known in advance. If multiple 081 * producers are used, the map returned by the given map factory should be thread-safe. 082 * 083 * @param keyType the type of the conflation key, used only to infer the generic type of the builder 084 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 085 * @param entryMapFactory the factory to create the map that manages entries per conflation key 086 * @param <K> the type of the conflation key 087 * @param <V> the type of elements in the queue 088 * @return a new builder 089 */ 090 static <K,V> ConflationQueueBuilder<K,V> builder(@SuppressWarnings("unused") final Class<K> keyType, 091 @SuppressWarnings("unused") final Class<V> valueType, 092 final Supplier<? extends Map<Object,Object>> entryMapFactory) { 093 return new ConflationQueueBuilderImpl.EntryMapFactoryBuilder<>(entryMapFactory); 094 } 095 096 /** 097 * Creates an initial builder given all conflation keys (exhaustive!). 098 * 099 * @param allConflationKeys an exhaustive list of all conflation keys that will ever be used for the queue 100 * @param <K> the type of the conflation key 101 * @param <V> the type of elements in the queue 102 * @return a new builder 103 */ 104 @SafeVarargs 105 static <K,V> ConflationQueueBuilder<K,V> declareAllConflationKeys(final K... allConflationKeys) { 106 //NOTE: this creates garbage 107 return declareAllConflationKeys(Arrays.asList(allConflationKeys)); 108 } 109 110 /** 111 * Creates an initial builder given all conflation keys (exhaustive!). 112 * 113 * @param allConflationKeys an exhaustive list of all conflation keys that will ever be used for the queue 114 * @param <K> the type of the conflation key 115 * @param <V> the type of elements in the queue 116 * @return a new builder 117 */ 118 static <K,V> ConflationQueueBuilder<K,V> declareAllConflationKeys(final List<K> allConflationKeys) { 119 return new ConflationQueueBuilderImpl.DeclaredKeysBuilder<>(allConflationKeys); 120 } 121 122 /** 123 * Creates an initial builder given all conflation keys (exhaustive!). 124 * 125 * @param allConflationKeys an exhaustive list of all conflation keys that will ever be used for the queue 126 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 127 * @param <K> the type of the conflation key 128 * @param <V> the type of elements in the queue 129 * @return a new builder 130 */ 131 static <K,V> ConflationQueueBuilder<K,V> declareAllConflationKeys(final List<K> allConflationKeys, 132 @SuppressWarnings("unused") final Class<V> valueType) { 133 return new ConflationQueueBuilderImpl.DeclaredKeysBuilder<>(allConflationKeys); 134 } 135 136 /** 137 * Creates an initial builder given the enum conflation key class. 138 * 139 * @param keyType the type of the conflation key 140 * @param <K> the type of the conflation key 141 * @param <V> the type of elements in the queue 142 * @return a new builder 143 */ 144 static <K extends Enum<K>,V> ConflationQueueBuilder<K,V> forEnumConflationKey(final Class<K> keyType) { 145 return new ConflationQueueBuilderImpl.EnumKeyBuilder<>(keyType); 146 } 147 148 /** 149 * Creates an initial builder given the enum conflation key class. 150 * 151 * @param keyType the type of the conflation key 152 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 153 * @param <K> the type of the conflation key 154 * @param <V> the type of elements in the queue 155 * @return a new builder 156 */ 157 static <K extends Enum<K>,V> ConflationQueueBuilder<K,V> forEnumConflationKey(final Class<K> keyType, 158 @SuppressWarnings("unused") final Class<V> valueType) { 159 return new ConflationQueueBuilderImpl.EnumKeyBuilder<>(keyType); 160 } 161 162 /** 163 * Register a listener as created by the specified supplier when creating queue appenders. The created listeners 164 * must be thread safe for multi-producer queues, e.g. consider using 165 * {@link AppenderListener#threadLocalSupplier(Supplier)}. 166 * 167 * @param listenerSupplier a listener supplier acting as listener factory 168 * @return the builder 169 */ 170 ConflationQueueBuilder<K,V> withAppenderListener(Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier); 171 172 /** 173 * Register a listener as created by the specified supplier when creating queue pollers. The created listeners 174 * must be thread safe for multi-consumer queues, e.g. consider using 175 * {@link PollerListener#threadLocalSupplier(Supplier)}. 176 * 177 * @param listenerSupplier a listener supplier acting as listener factory 178 * @return the builder 179 */ 180 ConflationQueueBuilder<K,V> withPollerListener(Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier); 181 182 /** 183 * Switch builder mode to create a conflation queue that allows exchanging of elements between the consumer and the 184 * producer, that is, the builder will now create a {@link ExchangeConflationQueue}. 185 * 186 * @return a builder for an {@link ExchangeConflationQueue}, more specifically an {@link EvictConflationQueue} 187 * @see ExchangeConflationQueue 188 * @see EvictConflationQueue 189 * @see #withMerging(Merger) 190 */ 191 ExchangeConflationQueueBuilder<K,V> withExchangeValueSupport(); 192 193 /** 194 * Switch builder mode to create a conflation queue that supports merging of old and new values when conflation 195 * occurs, that is, the builder will now create a {@link MergeConflationQueue}. 196 * 197 * @param merger merge strategy to use when conflation occurs 198 * @return a builder for an {@link ExchangeConflationQueue}, more specifically a {@link MergeConflationQueue} 199 * @see ExchangeConflationQueue 200 * @see MergeConflationQueue 201 * @see #withExchangeValueSupport() 202 */ 203 ExchangeConflationQueueBuilder<K,V> withMerging(Merger<? super K, V> merger); 204 205 /** 206 * Builds and returns a new conflation queue instance using the given queue factory for the backing queue. The 207 * backing queue determines whether single or multiple producers and consumers are supported. 208 * 209 * @param queueFactory the factory to create the backing queue 210 * @return a new conflation queue instance 211 */ 212 ConflationQueue<K,V> build(Supplier<? extends Queue<Object>> queueFactory); 213 214 /** 215 * Builder for {@link ExchangeConflationQueue} subtypes. 216 * 217 * @param <K> the type of the conflation key 218 * @param <V> the type of elements in the queue 219 */ 220 interface ExchangeConflationQueueBuilder<K,V> { 221 /** 222 * Register a listener as created by the specified supplier when creating queue appenders. The created listeners 223 * must be thread safe for multi-producer queues, e.g. consider using 224 * {@link AppenderListener#threadLocalSupplier(Supplier)}. 225 * 226 * @param listenerSupplier a listener supplier acting as listener factory 227 * @return the builder 228 */ 229 ExchangeConflationQueueBuilder<K,V> withAppenderListener(Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier); 230 231 /** 232 * Register a listener as created by the specified supplier when creating queue pollers. The created listeners 233 * must be thread safe for multi-consumer queues, e.g. consider using 234 * {@link PollerListener#threadLocalSupplier(Supplier)}. 235 * 236 * @param listenerSupplier a listener supplier acting as listener factory 237 * @return the builder 238 */ 239 ExchangeConflationQueueBuilder<K,V> withPollerListener(Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier); 240 241 /** 242 * Builds and returns a new exchange conflation queue instance using the given queue factory for the backing 243 * queue. The backing queue determines whether single or multiple producers and consumers are supported. 244 * 245 * @param queueFactory the factory to create the backing queue 246 * @return a new exchange conflation queue instance 247 */ 248 ExchangeConflationQueue<K,V> build(Supplier<? extends Queue<Object>> queueFactory); 249 } 250}