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