001/** 002 * The MIT License (MIT) 003 * 004 * Copyright (c) 2019 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.List; 027import java.util.Map; 028import java.util.Objects; 029import java.util.Queue; 030import java.util.function.Supplier; 031 032/** 033 * Package local builder implementation as returned by the static methods of {@link ConflationQueueBuilder}. 034 * 035 * @param <K> the conflation key type 036 * @param <V> the value type 037 */ 038class ConflationQueueBuilderImpl<K,V> implements ConflationQueueBuilder<K,V> { 039 040 private final CqFactory<K,V> cqFactory; 041 042 private Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier = () -> AppenderListener.NOOP; 043 private Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier = () -> PollerListener.NOOP; 044 045 private ConflationQueueBuilderImpl(final CqFactory<K,V> cqFactory) { 046 this.cqFactory = Objects.requireNonNull(cqFactory); 047 } 048 049 @Override 050 public ConflationQueueBuilder<K, V> withAppenderListener(final Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier) { 051 this.appenderListenerSupplier = Objects.requireNonNull(listenerSupplier); 052 return this; 053 } 054 055 @Override 056 public ConflationQueueBuilder<K, V> withPollerListener(final Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier) { 057 this.pollerListenerSupplier = Objects.requireNonNull(listenerSupplier); 058 return this; 059 } 060 061 @Override 062 public ExchangeConflationQueueBuilder<K,V> withExchangeValueSupport() { 063 return new EvictConflationQueueBuilder(); 064 } 065 066 @Override 067 public ExchangeConflationQueueBuilder<K, V> withMerging(final Merger<? super K, V> merger) { 068 return new MergeConflationQueueBuilder(merger); 069 } 070 071 @Override 072 public ConflationQueue<K,V> build(final Supplier<? extends Queue<Object>> queueFactory) { 073 return cqFactory.atomicQueue(queueFactory, appenderListenerSupplier, pollerListenerSupplier); 074 } 075 076 /** 077 * Builder-internal factory for different types of conflation queues. 078 * 079 * @param <K> the conflation key type 080 * @param <V> the value type 081 */ 082 interface CqFactory<K,V> { 083 /** 084 * Factory method for {@link AtomicConflationQueue} 085 * @param queueFactory factory for the backing queue 086 * @param appenderListenerSupplier supplier acting as appender listener factory 087 * @param pollerListenerSupplier supplier acting as poller listener factory 088 * @return a new {@link AtomicConflationQueue} instance 089 */ 090 AtomicConflationQueue<K,V> atomicQueue(Supplier<? extends Queue<Object>> queueFactory, 091 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 092 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier); 093 /** 094 * Factory method for {@link EvictConflationQueue}. 095 * @param queueFactory factory for the backing queue 096 * @param appenderListenerSupplier supplier acting as appender listener factory 097 * @param pollerListenerSupplier supplier acting as poller listener factory 098 * @return a new {@link EvictConflationQueue} instance 099 */ 100 EvictConflationQueue<K,V> evictQueue(Supplier<? extends Queue<Object>> queueFactory, 101 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 102 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier); 103 /** 104 * Factory method for {@link MergeConflationQueue}. 105 * @param queueFactory factory for the backing queue 106 * @param merger merge strategy to use when conflation occurs 107 * @param appenderListenerSupplier supplier acting as appender listener factory 108 * @param pollerListenerSupplier supplier acting as poller listener factory 109 * @return a new {@link MergeConflationQueue} instance 110 */ 111 MergeConflationQueue<K,V> mergeQueue(Supplier<? extends Queue<Object>> queueFactory, 112 Merger<? super K, V> merger, 113 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 114 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier); 115 } 116 117 /** 118 * Default builder for the case that no conflation keys are declared. 119 * 120 * @param <K> the conflation key type 121 * @param <V> the value type 122 */ 123 static class DefaultBuilder<K,V> extends ConflationQueueBuilderImpl<K,V> { 124 DefaultBuilder() { 125 super(new CqFactory<K, V>() { 126 @Override 127 public AtomicConflationQueue<K, V> atomicQueue(Supplier<? extends Queue<Object>> queueFactory, 128 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 129 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 130 return new AtomicConflationQueue<>(queueFactory, appenderListenerSupplier.get(), pollerListenerSupplier.get()); 131 } 132 133 @Override 134 public EvictConflationQueue<K, V> evictQueue(Supplier<? extends Queue<Object>> queueFactory, 135 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 136 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 137 return new EvictConflationQueue<>(queueFactory, appenderListenerSupplier, pollerListenerSupplier); 138 } 139 140 @Override 141 public MergeConflationQueue<K, V> mergeQueue(Supplier<? extends Queue<Object>> queueFactory, 142 Merger<? super K, V> merger, 143 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 144 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 145 return new MergeConflationQueue<>(queueFactory, merger, appenderListenerSupplier, pollerListenerSupplier); 146 } 147 }); 148 } 149 } 150 151 /** 152 * Builder for the case that an entry map factory has been provided. 153 * 154 * @param <K> the conflation key type 155 * @param <V> the value type 156 */ 157 static class EntryMapFactoryBuilder<K,V> extends ConflationQueueBuilderImpl<K,V> { 158 EntryMapFactoryBuilder(final Supplier<? extends Map<Object,Object>> entryMapFactory) { 159 super(new CqFactory<K, V>() { 160 @Override 161 public AtomicConflationQueue<K, V> atomicQueue(Supplier<? extends Queue<Object>> queueFactory, 162 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 163 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 164 return new AtomicConflationQueue<>(queueFactory, entryMapFactory, appenderListenerSupplier.get(), pollerListenerSupplier.get()); 165 } 166 167 @Override 168 public EvictConflationQueue<K, V> evictQueue(Supplier<? extends Queue<Object>> queueFactory, 169 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 170 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 171 return new EvictConflationQueue<>(queueFactory, entryMapFactory, appenderListenerSupplier, pollerListenerSupplier); 172 } 173 174 @Override 175 public MergeConflationQueue<K, V> mergeQueue(Supplier<? extends Queue<Object>> queueFactory, 176 Merger<? super K, V> merger, 177 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 178 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 179 return new MergeConflationQueue<>(queueFactory, entryMapFactory, merger, appenderListenerSupplier, pollerListenerSupplier); 180 } 181 }); 182 } 183 } 184 185 /** 186 * Builder for enum conflation key types. 187 * 188 * @param <K> the conflation key type 189 * @param <V> the value type 190 */ 191 static class EnumKeyBuilder<K extends Enum<K>,V> extends ConflationQueueBuilderImpl<K,V> { 192 EnumKeyBuilder(final Class<K> enumConflationKeyClass) { 193 super(new CqFactory<K, V>() { 194 @Override 195 public AtomicConflationQueue<K, V> atomicQueue(Supplier<? extends Queue<Object>> queueFactory, 196 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 197 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 198 return AtomicConflationQueue.forEnumConflationKey(queueFactory, enumConflationKeyClass, appenderListenerSupplier.get(), pollerListenerSupplier.get()); 199 } 200 201 @Override 202 public EvictConflationQueue<K, V> evictQueue(Supplier<? extends Queue<Object>> queueFactory, 203 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 204 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 205 return EvictConflationQueue.forEnumConflationKey(queueFactory, enumConflationKeyClass, appenderListenerSupplier, pollerListenerSupplier); 206 } 207 208 @Override 209 public MergeConflationQueue<K, V> mergeQueue(Supplier<? extends Queue<Object>> queueFactory, 210 Merger<? super K, V> merger, 211 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 212 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 213 return MergeConflationQueue.forEnumConflationKey(queueFactory, merger, enumConflationKeyClass, appenderListenerSupplier, pollerListenerSupplier); 214 } 215 }); 216 } 217 } 218 219 /** 220 * Builder for the case that conflation keys are declared. 221 * 222 * @param <K> the conflation key type 223 * @param <V> the value type 224 */ 225 static class DeclaredKeysBuilder<K,V> extends ConflationQueueBuilderImpl<K,V> { 226 DeclaredKeysBuilder(final List<? extends K> allConflationKeys) { 227 super(new CqFactory<K, V>() { 228 @Override 229 public AtomicConflationQueue<K, V> atomicQueue(Supplier<? extends Queue<Object>> queueFactory, 230 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 231 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 232 return new AtomicConflationQueue<>(queueFactory, allConflationKeys, appenderListenerSupplier.get(), pollerListenerSupplier.get()); 233 } 234 235 @Override 236 public EvictConflationQueue<K, V> evictQueue(Supplier<? extends Queue<Object>> queueFactory, 237 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 238 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 239 return new EvictConflationQueue<>(queueFactory, allConflationKeys, appenderListenerSupplier, pollerListenerSupplier); 240 } 241 242 @Override 243 public MergeConflationQueue<K, V> mergeQueue(Supplier<? extends Queue<Object>> queueFactory, 244 Merger<? super K, V> merger, 245 Supplier<? extends AppenderListener<? super K, ? super V>> appenderListenerSupplier, 246 Supplier<? extends PollerListener<? super K, ? super V>> pollerListenerSupplier) { 247 return new MergeConflationQueue<>(queueFactory, merger, allConflationKeys, appenderListenerSupplier, pollerListenerSupplier); 248 } 249 }); 250 } 251 } 252 253 /** 254 * Builder for {@link EvictConflationQueue}. 255 */ 256 class EvictConflationQueueBuilder implements ExchangeConflationQueueBuilder<K,V> { 257 @Override 258 public EvictConflationQueueBuilder withAppenderListener(final Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier) { 259 ConflationQueueBuilderImpl.this.withAppenderListener(listenerSupplier); 260 return this; 261 } 262 263 @Override 264 public EvictConflationQueueBuilder withPollerListener(final Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier) { 265 ConflationQueueBuilderImpl.this.withPollerListener(listenerSupplier); 266 return this; 267 } 268 269 @Override 270 public ExchangeConflationQueue<K, V> build(final Supplier<? extends Queue<Object>> queueFactory) { 271 return cqFactory.evictQueue(queueFactory, appenderListenerSupplier, pollerListenerSupplier); 272 } 273 } 274 275 /** 276 * Builder for {@link MergeConflationQueue}. 277 */ 278 class MergeConflationQueueBuilder implements ExchangeConflationQueueBuilder<K,V> { 279 private final Merger<? super K, V> merger; 280 MergeConflationQueueBuilder(final Merger<? super K, V> merger) { 281 this.merger = Objects.requireNonNull(merger); 282 } 283 @Override 284 public MergeConflationQueueBuilder withAppenderListener(final Supplier<? extends AppenderListener<? super K, ? super V>> listenerSupplier) { 285 ConflationQueueBuilderImpl.this.withAppenderListener(listenerSupplier); 286 return this; 287 } 288 289 @Override 290 public MergeConflationQueueBuilder withPollerListener(final Supplier<? extends PollerListener<? super K, ? super V>> listenerSupplier) { 291 ConflationQueueBuilderImpl.this.withPollerListener(listenerSupplier); 292 return this; 293 } 294 295 @Override 296 public MergeConflationQueue<K, V> build(final Supplier<? extends Queue<Object>> queueFactory) { 297 return cqFactory.mergeQueue(queueFactory, merger, appenderListenerSupplier, pollerListenerSupplier); 298 } 299 300 301 } 302}