diff --git a/apache-geode-extensions/src/main/java/org/springframework/geode/cache/AbstractCommonEventProcessingCacheListener.java b/apache-geode-extensions/src/main/java/org/springframework/geode/cache/AbstractCommonEventProcessingCacheListener.java new file mode 100644 index 00000000..ea04db17 --- /dev/null +++ b/apache-geode-extensions/src/main/java/org/springframework/geode/cache/AbstractCommonEventProcessingCacheListener.java @@ -0,0 +1,104 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package org.springframework.geode.cache; + +import org.apache.geode.cache.CacheListener; +import org.apache.geode.cache.EntryEvent; +import org.apache.geode.cache.RegionEvent; +import org.apache.geode.cache.util.CacheListenerAdapter; + +/** + * An {@link Class abstract base class} implementing the Apache Geode {@link CacheListener} interface + * by extending the {@link CacheListenerAdapter} base class, which processes all {@link EntryEvent EntryEvents} + * and {@link RegionEvent RegionEvents} using the same logic. + * + * @author John Blum + * @see org.apache.geode.cache.CacheListener + * @see org.apache.geode.cache.EntryEvent + * @see org.apache.geode.cache.RegionEvent + * @see org.apache.geode.cache.util.CacheListenerAdapter + * @since 1.1.0 + */ +public abstract class AbstractCommonEventProcessingCacheListener extends CacheListenerAdapter { + + @Override + public void afterCreate(EntryEvent event) { + processEntryEvent(event, EntryEventType.CREATE); + } + + @Override + public void afterDestroy(EntryEvent event) { + processEntryEvent(event, EntryEventType.DESTROY); + } + + @Override + public void afterInvalidate(EntryEvent event) { + processEntryEvent(event, EntryEventType.INVALIDATE); + } + + @Override + public void afterUpdate(EntryEvent event) { + processEntryEvent(event, EntryEventType.UPDATE); + } + + protected void processEntryEvent(EntryEvent event, EntryEventType eventType) { } + + @Override + public void afterRegionClear(RegionEvent event) { + processRegionEvent(event, RegionEventType.CLEAR); + } + + @Override + public void afterRegionCreate(RegionEvent event) { + processRegionEvent(event, RegionEventType.CREATE); + } + + @Override + public void afterRegionDestroy(RegionEvent event) { + processRegionEvent(event, RegionEventType.DESTROY); + } + + @Override + public void afterRegionInvalidate(RegionEvent event) { + processRegionEvent(event, RegionEventType.INVALIDATE); + } + + @Override + public void afterRegionLive(RegionEvent event) { + processRegionEvent(event, RegionEventType.LIVE); + } + + protected void processRegionEvent(RegionEvent event, RegionEventType eventType) { } + + public enum EntryEventType { + + CREATE, + DESTROY, + INVALIDATE, + UPDATE; + + } + + public enum RegionEventType { + + CLEAR, + CREATE, + DESTROY, + INVALIDATE, + LIVE; + + } +} diff --git a/apache-geode-extensions/src/test/java/org/springframework/geode/cache/AbstractCommonEventProcessingCacheListenerUnitTests.java b/apache-geode-extensions/src/test/java/org/springframework/geode/cache/AbstractCommonEventProcessingCacheListenerUnitTests.java new file mode 100644 index 00000000..9e0db2ef --- /dev/null +++ b/apache-geode-extensions/src/test/java/org/springframework/geode/cache/AbstractCommonEventProcessingCacheListenerUnitTests.java @@ -0,0 +1,169 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package org.springframework.geode.cache; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import org.apache.geode.cache.EntryEvent; +import org.apache.geode.cache.RegionEvent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +/** + * Unit Tests for {@link AbstractCommonEventProcessingCacheListener}. + * + * @author John Blum + * @see org.junit.Test + * @see org.mockito.Mockito + * @see org.apache.geode.cache.CacheListener + * @since 1.0.0 + */ +@RunWith(MockitoJUnitRunner.class) +public class AbstractCommonEventProcessingCacheListenerUnitTests { + + @Mock + private EntryEvent mockEntryEvent; + + @Mock + private RegionEvent mockRegionEvent; + + @Spy + private AbstractCommonEventProcessingCacheListener cacheListener; + + @Test + public void afterCreateCallsProcessEntryEventWithCreate() { + + this.cacheListener.afterCreate(this.mockEntryEvent); + + verify(this.cacheListener, times(1)).afterCreate(eq(this.mockEntryEvent)); + + verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent), + eq(AbstractCommonEventProcessingCacheListener.EntryEventType.CREATE)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterDestroyCallsProcessEntryEventWithDestroy() { + + this.cacheListener.afterDestroy(this.mockEntryEvent); + + verify(this.cacheListener, times(1)).afterDestroy(eq(this.mockEntryEvent)); + + verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent), + eq(AbstractCommonEventProcessingCacheListener.EntryEventType.DESTROY)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterInvalidateCallsProcessEntryEventWithInvalidate() { + + this.cacheListener.afterInvalidate(this.mockEntryEvent); + + verify(this.cacheListener, times(1)).afterInvalidate(eq(this.mockEntryEvent)); + + verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent), + eq(AbstractCommonEventProcessingCacheListener.EntryEventType.INVALIDATE)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterUpdateCallsProcessEntryEventWithUpdate() { + + this.cacheListener.afterUpdate(this.mockEntryEvent); + + verify(this.cacheListener, times(1)).afterUpdate(eq(this.mockEntryEvent)); + + verify(this.cacheListener, times(1)).processEntryEvent(eq(this.mockEntryEvent), + eq(AbstractCommonEventProcessingCacheListener.EntryEventType.UPDATE)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterRegionClearCallsProcessRegionEventWithClear() { + + this.cacheListener.afterRegionClear(this.mockRegionEvent); + + verify(this.cacheListener, times(1)).afterRegionClear(eq(this.mockRegionEvent)); + + verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent), + eq(AbstractCommonEventProcessingCacheListener.RegionEventType.CLEAR)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterRegionCreateCallsProcessRegionEventWithCreate() { + + this.cacheListener.afterRegionCreate(this.mockRegionEvent); + + verify(this.cacheListener, times(1)).afterRegionCreate(eq(this.mockRegionEvent)); + + verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent), + eq(AbstractCommonEventProcessingCacheListener.RegionEventType.CREATE)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterRegionDestroyCallsProcessRegionEventWithCreate() { + + this.cacheListener.afterRegionDestroy(this.mockRegionEvent); + + verify(this.cacheListener, times(1)).afterRegionDestroy(eq(this.mockRegionEvent)); + + verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent), + eq(AbstractCommonEventProcessingCacheListener.RegionEventType.DESTROY)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterRegionInvalidateCallsProcessRegionEventWithInvalidate() { + + this.cacheListener.afterRegionInvalidate(this.mockRegionEvent); + + verify(this.cacheListener, times(1)).afterRegionInvalidate(eq(this.mockRegionEvent)); + + verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent), + eq(AbstractCommonEventProcessingCacheListener.RegionEventType.INVALIDATE)); + + verifyNoMoreInteractions(this.cacheListener); + } + + @Test + public void afterRegionLiveCallsProcessRegionEventWithLive() { + + this.cacheListener.afterRegionLive(this.mockRegionEvent); + + verify(this.cacheListener, times(1)).afterRegionLive(eq(this.mockRegionEvent)); + + verify(this.cacheListener, times(1)).processRegionEvent(eq(this.mockRegionEvent), + eq(AbstractCommonEventProcessingCacheListener.RegionEventType.LIVE)); + + verifyNoMoreInteractions(this.cacheListener); + } +}