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.Queue; 029import java.util.function.Supplier; 030 031/** 032 * Builder for the different types of conflation queues serving as alternative to the queue constructors; a builder is 033 * returned by the static methods of this interface. 034 * 035 * @param <K> the type of the conflation key 036 * @param <V> the type of elements in the queue 037 */ 038public interface ConflationQueueBuilder<K,V> { 039 040 /** 041 * Creates an initial builder; use this method only when conflation keys are not known in advance 042 * @return a new builder 043 * 044 * @param <K> the type of the conflation key 045 * @param <V> the type of elements in the queue 046 */ 047 static <K,V> ConflationQueueBuilder<K,V> builder() { 048 return new ConflationQueueBuilderImpl.DefaultBuilder<>(); 049 } 050 051 /** 052 * Creates an initial builder; use this method only when conflation keys are not known in advance. 053 * 054 * @param keyType the type of the conflation key, used only to infer the generic type of the builder 055 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 056 * @param <K> the type of the conflation key 057 * @param <V> the type of elements in the queue 058 * @return a new builder 059 */ 060 static <K,V> ConflationQueueBuilder<K,V> builder(final Class<K> keyType, final Class<V> valueType) { 061 return new ConflationQueueBuilderImpl.DefaultBuilder<>(); 062 } 063 064 /** 065 * Creates an initial builder given all conflation keys (exhaustive!). 066 * 067 * @param allConflationKeys an exhaustive list of all conflation keys that will ever be used for the queue 068 * @param <K> the type of the conflation key 069 * @param <V> the type of elements in the queue 070 * @return a new builder 071 */ 072 @SafeVarargs 073 static <K,V> ConflationQueueBuilder<K,V> declareAllConflationKeys(final K... allConflationKeys) { 074 //NOTE: this creates garbage 075 return declareAllConflationKeys(Arrays.asList(allConflationKeys)); 076 } 077 078 /** 079 * Creates an initial builder given all conflation keys (exhaustive!). 080 * 081 * @param allConflationKeys an exhaustive list of all conflation keys that will ever be used for the queue 082 * @param <K> the type of the conflation key 083 * @param <V> the type of elements in the queue 084 * @return a new builder 085 */ 086 static <K,V> ConflationQueueBuilder<K,V> declareAllConflationKeys(final List<K> allConflationKeys) { 087 return new ConflationQueueBuilderImpl.DeclaredKeysBuilder<>(allConflationKeys); 088 } 089 090 /** 091 * Creates an initial builder given all conflation keys (exhaustive!). 092 * 093 * @param allConflationKeys an exhaustive list of all conflation keys that will ever be used for the queue 094 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 095 * @param <K> the type of the conflation key 096 * @param <V> the type of elements in the queue 097 * @return a new builder 098 */ 099 static <K,V> ConflationQueueBuilder<K,V> declareAllConflationKeys(final List<K> allConflationKeys, 100 final Class<V> valueType) { 101 return new ConflationQueueBuilderImpl.DeclaredKeysBuilder<>(allConflationKeys); 102 } 103 104 /** 105 * Creates an initial builder given the enum conflation key class. 106 * 107 * @param keyType the type of the conflation key 108 * @param <K> the type of the conflation key 109 * @param <V> the type of elements in the queue 110 * @return a new builder 111 */ 112 static <K extends Enum<K>,V> ConflationQueueBuilder<K,V> forEnumConflationKey(final Class<K> keyType) { 113 return new ConflationQueueBuilderImpl.EnumKeyBuilder<>(keyType); 114 } 115 116 /** 117 * Creates an initial builder given the enum conflation key class. 118 * 119 * @param keyType the type of the conflation key 120 * @param valueType the type of elements in the queue, used only to infer the generic type of the builder 121 * @param <K> the type of the conflation key 122 * @param <V> the type of elements in the queue 123 * @return a new builder 124 */ 125 static <K extends Enum<K>,V> ConflationQueueBuilder<K,V> forEnumConflationKey(final Class<K> keyType, 126 final Class<V> valueType) { 127 return new ConflationQueueBuilderImpl.EnumKeyBuilder<>(keyType); 128 } 129 130 /** 131 * Register a listener as created by the specified supplier when creating queue appenders. The created listeners 132 * must be thread safe for multi-producer queues, e.g. consider using 133 * {@link AppenderListener#threadLocalSupplier(Supplier)}. 134 * 135 * @param listenerSupplier a listener supplier acting as listener factory 136 * @return the builder 137 */ 138 ConflationQueueBuilder<K,V> withAppenderListener(Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier); 139 140 /** 141 * Register a listener as created by the specified supplier when creating queue pollers. The created listeners 142 * must be thread safe for multi-consumer queues, e.g. consider using 143 * {@link PollerListener#threadLocalSupplier(Supplier)}. 144 * 145 * @param listenerSupplier a listener supplier acting as listener factory 146 * @return the builder 147 */ 148 ConflationQueueBuilder<K,V> withPollerListener(Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier); 149 150 /** 151 * Switch builder mode to create a conflation queue that allows exchanging of elements between the consumer and the 152 * producer, that is, the builder will now create a {@link ExchangeConflationQueue}. 153 * 154 * @return a builder for an {@link ExchangeConflationQueue}, more specifically an {@link EvictConflationQueue} 155 * @see ExchangeConflationQueue 156 * @see EvictConflationQueue 157 * @see #withMerging(Merger) 158 */ 159 ExchangeConflationQueueBuilder<K,V> withExchangeValueSupport(); 160 161 /** 162 * Switch builder mode to create a conflation queue that supports merging of old and new values when conflation 163 * occurs, that is, the builder will now create a {@link MergeConflationQueue}. 164 * 165 * @param merger merge strategy to use when conflation occurs 166 * @return a builder for an {@link ExchangeConflationQueue}, more specifically a {@link MergeConflationQueue} 167 * @see ExchangeConflationQueue 168 * @see MergeConflationQueue 169 * @see #withExchangeValueSupport() 170 */ 171 ExchangeConflationQueueBuilder<K,V> withMerging(Merger<? super K, V> merger); 172 173 /** 174 * Builds and returns a new conflation queue instance using the given queue factory for the backing queue. The 175 * backing queue determines whether single or multiple producers and consumers are supported. 176 * 177 * @param queueFactory the factory to create the backing queue 178 * @return a new conflation queue instance 179 */ 180 ConflationQueue<K,V> build(Supplier<? extends Queue<Object>> queueFactory); 181 182 /** 183 * Builder for {@link ExchangeConflationQueue} subtypes. 184 * 185 * @param <K> the type of the conflation key 186 * @param <V> the type of elements in the queue 187 */ 188 interface ExchangeConflationQueueBuilder<K,V> { 189 /** 190 * Register a listener as created by the specified supplier when creating queue appenders. The created listeners 191 * must be thread safe for multi-producer queues, e.g. consider using 192 * {@link AppenderListener#threadLocalSupplier(Supplier)}. 193 * 194 * @param listenerSupplier a listener supplier acting as listener factory 195 * @return the builder 196 */ 197 ExchangeConflationQueueBuilder<K,V> withAppenderListener(Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier); 198 199 /** 200 * Register a listener as created by the specified supplier when creating queue pollers. The created listeners 201 * must be thread safe for multi-consumer queues, e.g. consider using 202 * {@link PollerListener#threadLocalSupplier(Supplier)}. 203 * 204 * @param listenerSupplier a listener supplier acting as listener factory 205 * @return the builder 206 */ 207 ExchangeConflationQueueBuilder<K,V> withPollerListener(Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier); 208 209 /** 210 * Builds and returns a new exchange conflation queue instance using the given queue factory for the backing 211 * queue. The backing queue determines whether single or multiple producers and consumers are supported. 212 * 213 * @param queueFactory the factory to create the backing queue 214 * @return a new exchange conflation queue instance 215 */ 216 ExchangeConflationQueue<K,V> build(Supplier<? extends Queue<Object>> queueFactory); 217 } 218}