text:
package org.apache.geode.internal.cache;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.SoftAssertions.assertSoftly;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;

import org.apache.geode.cache.DiskAccessException;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.query.internal.index.IndexManager;
import org.apache.geode.cache.query.internal.index.IndexProtocol;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.cache.TXEntryState.DistTxThinEntryState;
import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
import org.apache.geode.internal.cache.versions.VersionStamp;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.util.concurrent.ConcurrentMapWithReusableEntries;

@SuppressWarnings("unchecked")
public class AbstractRegionMapTxApplyDestroyTest {
  // parameters
  private Object key = "key";
  @Mock
  private TXId txId;
  private TXRmtEvent txEvent;
  private boolean inTokenMode;
  private boolean inRI;
  private Operation operation = Operation.DESTROY;
  @Mock
  private EventID eventId;
  private Object aCallbackArgument = "aCallbackArgument";
  private final List<EntryEventImpl> pendingCallbacks = new ArrayList<>();
  private FilterRoutingInfo filterRoutingInfo = null; // Provide a meaningful value for this?
  @Mock
  private ClientProxyMembershipID bridgeContext;
  private boolean isOriginRemote = false;
  @Mock
  private TXEntryState txEntryState;
  private VersionTag versionTag;
  private long tailKey = 223L;

  @Mock
  private InternalDistributedMember myId;
  @Mock
  private InternalDistributedMember remoteId;
  @Mock
  private KeyInfo keyInfo;
  @Mock
  private ConcurrentMapWithReusableEntries entryMap;
  @Mock
  private RegionEntryFactory regionEntryFactory;
  @Mock
  private RegionEntry existingRegionEntry;
  @Mock
  private RegionEntry factoryRegionEntry;
  @Mock
  private RegionEntry oldRegionEntry;
  @Mock
  private PartitionedRegion partitionedRegion;
  @Mock
  private VersionTag existingVersionTag;
  @Mock
  private CachePerfStats cachePerfStats;

  private LocalRegion owner;
  private TestableAbstractRegionMap regionMap;

  @Before
  public void setup() {
    initMocks(this);
    VersionStamp versionStamp = mock(VersionStamp.class);
    when(versionStamp.asVersionTag()).thenReturn(existingVersionTag);
    when(existingRegionEntry.getVersionStamp()).thenReturn(versionStamp);
    when(existingRegionEntry.getKey()).thenReturn(key);
    when(factoryRegionEntry.getKey()).thenReturn(key);
    when(oldRegionEntry.getKey()).thenReturn(key);
    when(keyInfo.getKey()).thenReturn(key);
    when(txId.getMemberId()).thenReturn(myId);
  }

  // tests for no region entry.
  // Each of these tests requires givenNotInTokenMode and givenNoConcurrencyChecks

  @Test
  public void txApplyDestroySetCorrectPendingCallback_givenNoRegionEntryNotInTokenModeNoConcurrencyChecks() {
    givenLocalRegion();
    givenNoRegionEntry();
    givenNotInTokenMode();
    givenNoConcurrencyChecks();
    when(owner.generateEventID()).thenReturn(true);
    when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);

    doTxApplyDestroy();
    assertThat(pendingCallbacks).hasSize(1);
    EntryEventImpl callbackEvent = pendingCallbacks.get(0);

    // noinspection Duplicates
    assertSoftly(softly -> {
      softly.assertThat(callbackEvent.getRegion()).isSameAs(owner);
      softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
      softly.assertThat(callbackEvent.getKey()).isSameAs(key);
      softly.assertThat(callbackEvent.getNewValue()).isNull();
      softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
      softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
      softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
      softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
      softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
      softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
      softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
      softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
    });
  }

  @Test
  public void addsCallbackEvent_givenNoRegionEntryNotInTokenModeNoConcurrencyChecks_andBucket() {
    givenBucketRegion();
    givenNoRegionEntry();
    givenNotInTokenMode();
    givenNoConcurrencyChecks();

    when(partitionedRegion.generateEventID()).thenReturn(true);
    when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);

    doTxApplyDestroy();

    verify(owner, times(1)).handleWANEvent(any());
    verify(txEntryState, times(1)).setTailKey(tailKey);

    assertThat(pendingCallbacks).hasSize(1);
    EntryEventImpl callbackEvent = pendingCallbacks.get(0);

    // noinspection Duplicates
    assertSoftly(softly -> {
      softly.assertThat(callbackEvent.getRegion()).isSameAs(partitionedRegion);
      softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
      softly.assertThat(callbackEvent.getKey()).isSameAs(key);
      softly.assertThat(callbackEvent.getNewValue()).isNull();
      softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
      softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
      softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
      softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
      softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
      softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
      softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
      softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
    });
  }

  @Test
  public void txApplyDestroyCallReleaseEvent_givenNoRegionEntryNotInTokenModeNoConcurrencyChecksAndBucket_whenHandleWANEventThrows() {
    givenBucketRegion();
    givenNoRegionEntry();
    givenNotInTokenMode();
    givenNoConcurrencyChecks();
    doThrow(RuntimeException.class).when(owner).handleWANEvent(any());

    assertThatThrownBy(this::doTxApplyDestroy).isInstanceOf(RuntimeException.class);

    verify(regionMap, times(1)).releaseEvent(any());
  }

  // tests for "existingRegionEntry"

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryThatIsRemoved() {
    givenLocalRegion();
    givenExistingRegionEntry();
    when(existingRegionEntry.isRemoved()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyInvokesRescheduleTombstone_givenExistingRegionEntryThatIsTombstone() {
    givenLocalRegion();
    givenExistingRegionEntry();
    when(existingRegionEntry.isRemoved()).thenReturn(true);
    when(existingRegionEntry.isTombstone()).thenReturn(true);

    doTxApplyDestroy();

    verify(owner, times(1)).rescheduleTombstone(same(existingRegionEntry), any());
  }

  @Test
  public void doesNotAddCallbackEvent_ifExistingRegionEntryIsTombstone() throws Exception {
    givenLocalRegion();
    givenExistingRegionEntry();
    when(existingRegionEntry.isRemoved()).thenReturn(true);
    when(existingRegionEntry.isTombstone()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(existingRegionEntry, never()).makeTombstone(any(), any());
    verify(txEntryState, never()).setVersionTag(any());
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryWithInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    this.inTokenMode = true;
    this.inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key),
        eq(this.inTokenMode), eq(false), eq(false));
  }

  @Test
  public void doesNotAddCallbackEvent_givenExistingRegionEntryWithInTokenModeAndNotInRI()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    this.inTokenMode = true;
    this.inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(owner).generateAndSetVersionTag(any(EntryEventImpl.class), same(existingRegionEntry));
    verify(existingRegionEntry, never()).makeTombstone(any(), any());
    verify(txEntryState).setVersionTag(any());
  }

  @Test
  public void setsRegionEntryOnEvent_ifExistingRegionEntryIsValid() throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();

    Object oldValue = "oldValue";
    when(existingRegionEntry.getValueInVM(owner)).thenReturn(oldValue);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).size().isEqualTo(1);
    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.getRegionEntry()).isSameAs(existingRegionEntry);
    assertThat(event.getOldValue()).isSameAs(oldValue);

    verify(owner).generateAndSetVersionTag(any(EntryEventImpl.class), same(existingRegionEntry));
    verify(existingRegionEntry, never()).makeTombstone(any(), any());
    verify(txEntryState).setVersionTag(event.getVersionTag());
  }

  @Test
  public void txApplyDestroyUpdateIndexes_givenExistingRegionEntryThatIsValid() throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    IndexManager indexManager = mock(IndexManager.class);
    when(owner.getIndexManager()).thenReturn(indexManager);

    doTxApplyDestroy();

    verify(indexManager, times(1)).updateIndexes(same(existingRegionEntry),
        eq(IndexManager.REMOVE_ENTRY), eq(IndexProtocol.OTHER_OP));
  }

  @Test
  public void txApplyDestroyCallsAddDestroy_givenExistingRegionEntryThatIsValidAndTxRmtEvent() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    txEvent = mock(TXRmtEvent.class);

    doTxApplyDestroy();

    verify(txEvent, times(1)).addDestroy(same(owner), same(existingRegionEntry), eq(key),
        same(aCallbackArgument));
  }

  @Test
  public void callsProcessAndGenerateTXVersionTag_givenExistingRegionEntryThatIsValid() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl callbackEvent = pendingCallbacks.get(0);
    verify(regionMap, times(1)).processAndGenerateTXVersionTag(same(callbackEvent),
        same(existingRegionEntry), same(txEntryState));
    assertThat(callbackEvent.getNextRegionVersion()).isEqualTo(-1L); // Default value
  }

  @Test
  public void setsEventNextRegionVersionOnCallbackEvent_givenExistingRegionEntryThatIsValidAndDistTxEntryStateExists() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();

    DistTxThinEntryState distTxEntryStates = mock(DistTxThinEntryState.class);
    when(txEntryState.getDistTxEntryStates()).thenReturn(distTxEntryStates);
    when(distTxEntryStates.getRegionVersion()).thenReturn(999L);

    doTxApplyDestroy();

    EntryEventImpl callbackEvent = pendingCallbacks.get(0);
    assertThat(callbackEvent.getNextRegionVersion()).isEqualTo(999L); // Default value
  }

  @Test
  public void txApplyDestroySetsValueToDestroyToken_givenExistingRegionEntryThatIsValidWithInTokenMode()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(existingRegionEntry, times(1)).setValue(same(owner), eq(Token.DESTROYED));
  }

  @Test
  public void txApplyDestroyHandlesClear_givenExistingRegionEntryThatIsValidWithInTokenModeAndSetValueThrowsRegionClearedException()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = true;
    doThrow(RegionClearedException.class).when(existingRegionEntry).setValue(same(owner),
        eq(Token.DESTROYED));

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(any(), any(), anyBoolean(), eq(true), anyBoolean());
    verify(regionMap, never()).lruEntryDestroy(any());
  }

  @Test
  public void txApplyDestroyHandlesNoClear_givenExistingRegionEntryThatIsValidWithInTokenMode() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(any(), any(), anyBoolean(), eq(false),
        anyBoolean());
    verify(regionMap, times(1)).lruEntryDestroy(any());
  }

  @Test
  public void txApplyDestroyCallsUnscheduleTombstone_givenExistingRegionEntryThatIsTombstoneWithInTokenMode() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = true;
    when(existingRegionEntry.getValueInVM(owner)).thenReturn(Token.TOMBSTONE);

    doTxApplyDestroy();

    verify(owner, times(1)).unscheduleTombstone(same(existingRegionEntry));
  }

  @Test
  public void txApplyDestroyCallsRemoveEntry_givenExistingRegionEntryThatIsValidWithoutInTokenModeWithoutConcurrencyCheck()
      throws Exception {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = false;

    doTxApplyDestroy();

    verify(existingRegionEntry, times(1)).removePhase1(same(owner), eq(false));
    verify(existingRegionEntry, times(1)).removePhase2();
    verify(regionMap, times(1)).removeEntry(eq(key), same(existingRegionEntry), eq(false));
  }

  @Test
  public void txApplyDestroyCallsRescheduleTombstone_givenExistingRegionEntryThatIsValidWithoutInTokenModeWithConcurrencyCheckButNoVersionTag()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = false;
    versionTag = null;

    doTxApplyDestroy();

    verify(existingRegionEntry, times(1)).removePhase1(same(owner), eq(false));
    verify(existingRegionEntry, times(1)).removePhase2();
    verify(regionMap, times(1)).removeEntry(eq(key), same(existingRegionEntry), eq(false));
  }

  @Test
  public void txApplyDestroyCallsMakeTombstone_givenExistingRegionEntryThatIsValidWithoutInTokenModeWithConcurrencyCheckAndVersionTag()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = false;
    versionTag = mock(VersionTag.class);

    doTxApplyDestroy();

    verify(existingRegionEntry, times(1)).makeTombstone(same(owner), same(versionTag));
  }

  @Test
  public void txApplyDestroyCallsUpdateSizeOnRemove_givenExistingRegionEntryThatIsValid() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    int oldSize = 79;
    when(owner.calculateRegionEntryValueSize(same(existingRegionEntry))).thenReturn(oldSize);

    doTxApplyDestroy();

    verify(owner, times(1)).updateSizeOnRemove(eq(key), eq(oldSize));
  }

  @Test
  public void txApplyDestroyCallsReleaseEvent_givenExistingRegionEntry() {
    givenLocalRegion();
    givenExistingRegionEntry();

    doTxApplyDestroy();

    verify(regionMap, times(1)).releaseEvent(any());
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithoutInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = false;
    inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));

  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRemovedRegionEntryWithoutInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRemovedRegionEntry();
    inTokenMode = false;
    inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));

  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithoutInTokenModeAndWithInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = false;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRemovedRegionEntryWithoutInTokenModeAndWithInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRemovedRegionEntry();
    inTokenMode = false;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithInTokenModeAndInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRegionEntry();
    inTokenMode = true;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRemovedRegionEntryWithInTokenModeAndInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenExistingRemovedRegionEntry();
    inTokenMode = true;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenExistingRegionEntry();

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenExistingRemovedRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenExistingRemovedRegionEntry();

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyCallsHandleWanEvent_givenExistingRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenExistingRegionEntry();

    doTxApplyDestroy();

    verify(owner, times(1)).handleWANEvent(any());
    verify(txEntryState, times(1)).setTailKey(tailKey);
  }

  @Test
  public void txApplyDestroyDoesNotCallSetVersionTag_givenExistingRegionEntryWithPartitionedRegionButNoConcurrencyChecks() {
    givenBucketRegion();
    givenExistingRegionEntry();
    versionTag = mock(VersionTag.class);
    givenNoConcurrencyChecks();

    doTxApplyDestroy();

    verify(txEntryState, never()).setVersionTag(any());
  }

  @Test
  public void txApplyDestroyPreparesAndReleasesIndexManager_givenExistingRegionEntryWithIndexManager() {
    givenLocalRegion();
    givenExistingRegionEntry();
    IndexManager indexManager = mock(IndexManager.class);
    when(owner.getIndexManager()).thenReturn(indexManager);

    doTxApplyDestroy();

    InOrder inOrder = inOrder(indexManager);
    inOrder.verify(indexManager, times(1)).waitForIndexInit();
    inOrder.verify(indexManager, times(1)).countDownIndexUpdaters();
  }

  @Test
  public void txApplyDestroyCallsSetVersionTag_givenExistingRegionEntryWithPartitionedRegionAndConcurrencyChecks() {
    givenBucketRegion();
    givenExistingRegionEntry();
    versionTag = mock(VersionTag.class);
    givenConcurrencyChecks();

    doTxApplyDestroy();

    verify(txEntryState, times(1)).setVersionTag(same(versionTag));
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenExistingRegionEntryWithoutConcurrencyChecks() {
    givenLocalRegion();
    givenExistingRegionEntry();
    givenNoConcurrencyChecks();

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenExistingRemovedRegionEntryWithoutConcurrencyChecks() {
    givenLocalRegion();
    givenExistingRemovedRegionEntry();
    givenNoConcurrencyChecks();

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithShouldDispatchListenerEvent() {
    givenLocalRegion();
    givenExistingRegionEntry();
    when(owner.shouldDispatchListenerEvent()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRemovedRegionEntryWithShouldDispatchListenerEvent() {
    givenLocalRegion();
    givenExistingRemovedRegionEntry();
    when(owner.shouldDispatchListenerEvent()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRegionEntryWithshouldNotifyBridgeClients() {
    givenLocalRegion();
    givenExistingRegionEntry();
    when(owner.shouldNotifyBridgeClients()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenExistingRemovedRegionEntryWithshouldNotifyBridgeClients() {
    givenLocalRegion();
    givenExistingRemovedRegionEntry();
    when(owner.shouldNotifyBridgeClients()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    verify(owner, times(1)).txApplyDestroyPart2(same(existingRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyDoesCallTxApplyDestroyPart2_givenFactoryRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    versionTag = mock(VersionTag.class);

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(same(factoryRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  // tests for "factoryRegionEntry" (that is, no existing region entry and no oldRegionEntry).
  // All these tests require no existing region entry (that is, not found by getEntry).
  // All these tests need one of the following: givenConcurrencyChecks OR inTokenMode

  @Test
  public void txApplyDestroyCallsCreateEntry_givenFactoryRegionEntryAndInTokenMode() {
    givenLocalRegion();
    givenFactoryRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(regionEntryFactory, times(1)).createEntry(same(owner), eq(key),
        eq(Token.REMOVED_PHASE1));
  }

  @Test
  public void txApplyDestroyCallsCreateEntry_givenFactoryRegionEntryAndConcurrencyChecks() {
    givenLocalRegion();
    givenFactoryRegionEntry();
    givenConcurrencyChecks();

    doTxApplyDestroy();

    verify(regionEntryFactory, times(1)).createEntry(same(owner), eq(key),
        eq(Token.REMOVED_PHASE1));
  }

  @Test
  public void txApplyDestroyPreparesAndReleasesIndexManager_givenFactoryRegionEntryAndConcurrencyChecksWithIndexManager() {
    givenLocalRegion();
    givenFactoryRegionEntry();
    givenConcurrencyChecks();
    IndexManager indexManager = mock(IndexManager.class);
    when(owner.getIndexManager()).thenReturn(indexManager);

    doTxApplyDestroy();

    InOrder inOrder = inOrder(indexManager);
    inOrder.verify(indexManager, times(1)).waitForIndexInit();
    inOrder.verify(indexManager, times(1)).countDownIndexUpdaters();
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenFactoryRegionEntryWithInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = true;
    inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithoutInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = false;
    inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithoutInTokenModeAndWithInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = false;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithInTokenModeAndInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = true;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenFactoryRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    when(partitionedRegion.getConcurrencyChecksEnabled()).thenReturn(false);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenFactoryRegionEntryWithoutConcurrencyChecksInTokenMode() {
    givenLocalRegion();
    givenFactoryRegionEntry();
    givenNoConcurrencyChecks();
    inTokenMode = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithShouldDispatchListenerEvent() {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = true;
    inRI = true;
    when(owner.shouldDispatchListenerEvent()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenFactoryRegionEntryWithshouldNotifyBridgeClients() {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = true;
    inRI = true;
    when(owner.shouldNotifyBridgeClients()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroySetsRegionEntryOnEvent_givenFactoryRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.getRegionEntry()).isSameAs(factoryRegionEntry);
  }

  @Test
  public void txApplyDestroySetsOldValueOnEventToNotAvailable_givenFactoryRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.getRawOldValue()).isSameAs(Token.NOT_AVAILABLE);
  }

  @Test
  public void txApplyDestroyCallsHandleWanEvent_givenFactoryRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    verify(owner, times(1)).handleWANEvent(any());
    verify(txEntryState, times(1)).setTailKey(tailKey);
  }

  @Test
  public void txApplyDestroyCallsProcessAndGenerateTXVersionTag_givenFactoryRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    verify(regionMap, times(1)).processAndGenerateTXVersionTag(any(), same(factoryRegionEntry),
        same(txEntryState));
  }

  @Test
  public void txApplyDestroySetsRemoteOrigin_givenFactoryRegionEntryAndRemoteTxId() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    when(txId.getMemberId()).thenReturn(remoteId);

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.isOriginRemote()).isTrue();
  }

  @Test
  public void txApplyDestroySetsRemoteOrigin_givenFactoryRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.isOriginRemote()).isFalse();
  }

  @Test
  public void txApplyDestroySetsRegionOnEvent_givenFactoryRegionEntryAndBucket() {
    givenBucketRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.getRegion()).isSameAs(partitionedRegion);
  }

  @Test
  public void txApplyDestroyNeverCallsUpdateSizeOnCreate_givenFactoryRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    verify(owner, never()).updateSizeOnCreate(any(), anyInt());
  }

  @Test
  public void txApplyDestroyCallsMakeTombstone_givenFactoryRegionEntryWithConcurrencyCheckAndVersionTag()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    versionTag = mock(VersionTag.class);

    doTxApplyDestroy();

    verify(factoryRegionEntry, times(1)).makeTombstone(same(owner), same(versionTag));
  }

  @Test
  public void txApplyDestroyNeverCallsMakeTombstone_givenFactoryRegionEntryWithConcurrencyCheckButNoVersionTag()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    verify(factoryRegionEntry, never()).makeTombstone(any(), any());
  }

  @Test
  public void txApplyDestroyNeverCallsMakeTombstone_givenFactoryRegionEntryWithoutConcurrencyCheckButWithInTokenModeAndVersionTag()
      throws Exception {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenFactoryRegionEntry();
    inTokenMode = true;
    versionTag = mock(VersionTag.class);

    doTxApplyDestroy();

    verify(factoryRegionEntry, never()).makeTombstone(any(), any());
  }

  @Test
  public void txApplyDestroyCallsRemoveEntry_givenFactoryRegionEntryWithConcurrencyCheck()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();

    doTxApplyDestroy();

    verify(factoryRegionEntry, times(1)).removePhase1(same(owner), eq(false));
    verify(factoryRegionEntry, times(1)).removePhase2();
    verify(regionMap, times(1)).removeEntry(eq(key), same(factoryRegionEntry), eq(false));
  }

  @Test
  public void txApplyDestroyCallsReleaseEvent_givenFactoryRegionEntryWithoutConcurrencyChecksInTokenMode() {
    givenLocalRegion();
    givenFactoryRegionEntry();
    givenNoConcurrencyChecks();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(regionMap, times(1)).releaseEvent(any());
  }

  @Test
  public void txApplyDestroyCallsSetValueWithDestroyedToken_givenFactoryRegionEntryWithoutConcurrencyChecksInTokenMode()
      throws RegionClearedException {
    givenLocalRegion();
    givenFactoryRegionEntry();
    givenNoConcurrencyChecks();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(factoryRegionEntry, times(1)).setValue(same(owner), eq(Token.DESTROYED));
  }

  @Test
  public void txApplyDestroyDoesNotCallSetVersionTag_givenFactoryRegionEntryWithPartitionedRegionButNoConcurrencyChecks() {
    givenBucketRegion();
    givenFactoryRegionEntry();
    versionTag = mock(VersionTag.class);
    givenNoConcurrencyChecks();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(txEntryState, never()).setVersionTag(any());
  }

  @Test
  public void txApplyDestroyDoesNotCallSetVersionTag_givenFactoryRegionEntryWithPartitionedRegionAndConcurrencyChecks() {
    givenBucketRegion();
    givenFactoryRegionEntry();
    versionTag = mock(VersionTag.class);
    givenConcurrencyChecks();

    doTxApplyDestroy();

    verify(txEntryState, times(1)).setVersionTag(same(versionTag));
  }

  @Test
  public void txApplyDestroyDoesNotCallTxApplyDestroyPart2_givenFactoryRegionEntryWithMakeTombstoneThrowingRegionDestroyedException()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenFactoryRegionEntry();
    versionTag = mock(VersionTag.class);
    doThrow(RegionClearedException.class).when(factoryRegionEntry).makeTombstone(any(), any());

    doTxApplyDestroy();

    verify(owner, never()).txApplyDestroyPart2(any(), any(), anyBoolean(), anyBoolean(),
        anyBoolean());
  }

  // tests for "oldRegionEntry" (that is, an existing region entry found by putIfAbsent).
  // All these tests require no existing region entry (that is, not found by getEntry).
  // All these tests need one of the following: givenConcurrencyChecks OR inTokenMode

  @Test
  public void txApplyDestroyRetries_givenOldRegionEntryWithRemovedPhase2() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;
    when(oldRegionEntry.isRemovedPhase2()).thenReturn(true).thenReturn(false);

    doTxApplyDestroy();

    verify(cachePerfStats, times(1)).incRetries();
    verify(entryMap, times(1)).remove(eq(key), same(oldRegionEntry));
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenOldRegionEntryWithInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;
    inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenOldRegionEntrydWithoutInTokenModeAndNotInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = false;
    inRI = false;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenOldRegionEntryWithoutInTokenModeAndWithInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = false;
    inRI = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void addsCallbackEvent_givenOldRegionEntryWithInTokenModeAndInRI() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;
    inRI = true;

    when(owner.generateEventID()).thenReturn(true);
    when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
    EntryEventImpl callbackEvent = pendingCallbacks.get(0);

    // noinspection Duplicates
    assertSoftly(softly -> {
      softly.assertThat(callbackEvent.getRegion()).isSameAs(owner);
      softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
      softly.assertThat(callbackEvent.getKey()).isSameAs(key);
      softly.assertThat(callbackEvent.getNewValue()).isNull();
      softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
      softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
      softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
      softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
      softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
      softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
      softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
      softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
      softly.assertThat(callbackEvent.getRegionEntry()).isSameAs(oldRegionEntry);
      softly.assertThat(callbackEvent.getOldValue()).isNull();
    });
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenOldRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    when(partitionedRegion.getConcurrencyChecksEnabled()).thenReturn(false);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyHasNoPendingCallback_givenOldRegionEntryWithoutConcurrencyChecksInTokenMode() {
    givenLocalRegion();
    givenOldRegionEntry();
    givenNoConcurrencyChecks();
    inTokenMode = true;

    doTxApplyDestroy();

    assertThat(pendingCallbacks).isEmpty();
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenOldRegionEntryWithShouldDispatchListenerEvent() {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;
    inRI = true;
    when(owner.shouldDispatchListenerEvent()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroyHasPendingCallback_givenOldRegionEntryWithshouldNotifyBridgeClients() {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;
    inRI = true;
    when(owner.shouldNotifyBridgeClients()).thenReturn(true);

    doTxApplyDestroy();

    assertThat(pendingCallbacks).hasSize(1);
  }

  @Test
  public void txApplyDestroySetsRegionEntryOnEvent_givenOldRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.getRegionEntry()).isSameAs(oldRegionEntry);
  }

  @Test
  public void txApplyDestroySetsOldValueOnEventToNotAvailable_givenOldRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.getRawOldValue()).isSameAs(Token.NOT_AVAILABLE);
  }

  @Test
  public void txApplyDestroyCallsHandleWanEvent_givenOldRegionEntryWithPartitionedRegion() {
    givenBucketRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    verify(owner, times(1)).handleWANEvent(any());
    verify(txEntryState, times(1)).setTailKey(tailKey);
  }

  @Test
  public void txApplyDestroyCallsProcessAndGenerateTXVersionTag_givenOldRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    verify(regionMap, times(1)).processAndGenerateTXVersionTag(any(), same(oldRegionEntry),
        same(txEntryState));
  }

  @Test
  public void txApplyDestroySetsRemoteOrigin_givenOldRegionEntryAndRemoteTxId() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    when(txId.getMemberId()).thenReturn(remoteId);

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.isOriginRemote()).isTrue();
  }

  @Test
  public void txApplyDestroySetsRemoteOrigin_givenOldRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    EntryEventImpl event = pendingCallbacks.get(0);
    assertThat(event.isOriginRemote()).isFalse();
  }

  @Test
  public void addsCallbackEvent_givenOldRegionEntryAndBucket() {
    givenBucketRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    when(partitionedRegion.generateEventID()).thenReturn(true);
    when(keyInfo.getCallbackArg()).thenReturn(aCallbackArgument);

    doTxApplyDestroy();

    EntryEventImpl callbackEvent = pendingCallbacks.get(0);

    // noinspection Duplicates
    assertSoftly(softly -> {
      softly.assertThat(callbackEvent.getRegion()).isSameAs(partitionedRegion);
      softly.assertThat(callbackEvent.getOperation()).isSameAs(operation);
      softly.assertThat(callbackEvent.getKey()).isSameAs(key);
      softly.assertThat(callbackEvent.getNewValue()).isNull();
      softly.assertThat(callbackEvent.getTransactionId()).isSameAs(txId);
      softly.assertThat(callbackEvent.getEventId()).isSameAs(eventId);
      softly.assertThat(callbackEvent.getCallbackArgument()).isSameAs(aCallbackArgument);
      softly.assertThat(callbackEvent.getLocalFilterInfo()).isSameAs(filterRoutingInfo);
      softly.assertThat(callbackEvent.getContext()).isSameAs(bridgeContext);
      softly.assertThat(callbackEvent.isOriginRemote()).isEqualTo(isOriginRemote);
      softly.assertThat(callbackEvent.getVersionTag()).isEqualTo(versionTag);
      softly.assertThat(callbackEvent.getTailKey()).isEqualTo(tailKey);
      softly.assertThat(callbackEvent.getRegionEntry()).isSameAs(oldRegionEntry);
      softly.assertThat(callbackEvent.getOldValue()).isNull();
    });
  }

  @Test
  public void txApplyDestroyCallUpdateSizeOnRemoveWithZero_givenOldRegionEntryThatIsTombstone() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    when(oldRegionEntry.isTombstone()).thenReturn(true);

    doTxApplyDestroy();

    verify(owner, times(1)).updateSizeOnRemove(eq(key), eq(0));
  }

  @Test
  public void txApplyDestroyCallUpdateSizeOnRemoveWithOldSize_givenOldRegionEntryThatIsNotTombstone() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    int oldSize = 79;
    when(owner.calculateRegionEntryValueSize(oldRegionEntry)).thenReturn(oldSize);
    when(oldRegionEntry.isTombstone()).thenReturn(false);

    doTxApplyDestroy();

    verify(owner, times(1)).updateSizeOnRemove(eq(key), eq(oldSize));
  }

  @Test
  public void txApplyDestroySetsValueToTokenDestroyed_givenOldRegionEntry() throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    verify(oldRegionEntry, times(1)).setValue(same(owner), eq(Token.DESTROYED));
  }

  @Test
  public void txApplyDestroySetsValueToTokenDestroyed_givenOldRegionEntryAndInTokenMode()
      throws Exception {
    givenLocalRegion();
    givenNoConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(oldRegionEntry, times(1)).setValue(same(owner), eq(Token.DESTROYED));
  }

  @Test
  public void txApplyDestroyCallsUnscheduleTombstone_givenOldRegionEntryThatIsTombstone() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    when(oldRegionEntry.isTombstone()).thenReturn(true);

    doTxApplyDestroy();

    verify(owner, times(1)).unscheduleTombstone(same(oldRegionEntry));
  }

  @Test
  public void txApplyDestroyCallsTxApplyDestroyPart2_givenOldRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyCallsTxApplyDestroyPart2_givenOldRemovedRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRemovedRegionEntry();

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyCallsTxApplyDestroyPart2_givenOldRegionEntryWithInTokenMode() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(false));
  }

  @Test
  public void txApplyDestroyCallsTxApplyDestroyPart2_givenOldRemovedRegionEntryWithInTokenMode() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRemovedRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key), eq(inTokenMode),
        eq(false), eq(true));
  }

  @Test
  public void txApplyDestroyCallsLruEntryDestroy_givenOldRegionEntry() {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    verify(regionMap, times(1)).lruEntryDestroy(oldRegionEntry);
  }

  @Test
  public void txApplyDestroyCallsReleaseEvent_givenOldRegionEntryWithoutConcurrencyChecksInTokenMode() {
    givenLocalRegion();
    givenOldRegionEntry();
    givenNoConcurrencyChecks();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(regionMap, times(1)).releaseEvent(any());
  }

  @Test
  public void txApplyDestroyDoesCallTxApplyDestroyPart2_givenOldRegionEntryWithMakeTombstoneThrowingRegionDestroyedException()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    doThrow(RegionClearedException.class).when(oldRegionEntry).setValue(any(), any());

    doTxApplyDestroy();

    verify(owner, times(1)).txApplyDestroyPart2(same(oldRegionEntry), eq(key), eq(inTokenMode),
        eq(true), eq(true));
  }

  @Test
  public void txApplyDestroyCallsMakeTombstone_givenOldRegionEntryWithConcurrencyCheckAndVersionTag()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    versionTag = mock(VersionTag.class);

    doTxApplyDestroy();

    verify(oldRegionEntry, times(1)).makeTombstone(same(owner), same(versionTag));
  }

  @Test
  public void txApplyDestroyCallsRemoveEntry_givenOldRegionEntry() throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();

    doTxApplyDestroy();

    verify(oldRegionEntry, never()).makeTombstone(any(), any());
    verify(oldRegionEntry, times(1)).removePhase1(same(owner), eq(false));
    verify(oldRegionEntry, times(1)).removePhase2();
    verify(regionMap, times(1)).removeEntry(eq(key), same(oldRegionEntry), eq(false));
  }

  @Test
  public void txApplyDestroyNeverCallsRemoveEntry_givenOldRegionEntryAndInTokenMode()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    inTokenMode = true;

    doTxApplyDestroy();

    verify(oldRegionEntry, never()).makeTombstone(any(), any());
    verify(oldRegionEntry, never()).removePhase1(any(), anyBoolean());
    verify(oldRegionEntry, never()).removePhase2();
    verify(regionMap, never()).removeEntry(any(), any(), anyBoolean());
  }

  @Test
  public void txApplyDestroyDoesCallsHandleDiskAccessException_givenOldRegionEntrySetValueThatThrowsDiskAccessException()
      throws Exception {
    givenLocalRegion();
    givenConcurrencyChecks();
    givenOldRegionEntry();
    doThrow(DiskAccessException.class).when(oldRegionEntry).setValue(any(), any());

    assertThatThrownBy(this::doTxApplyDestroy).isInstanceOf(DiskAccessException.class);

    verify(owner, times(1)).handleDiskAccessException(any());
  }

  // helper methods for the tests

  private void givenNoRegionEntry() {
    when(entryMap.get(eq(key))).thenReturn(null);
  }

  private void givenExistingRegionEntry() {
    when(entryMap.get(eq(key))).thenReturn(existingRegionEntry);
  }

  private void givenExistingRemovedRegionEntry() {
    givenExistingRegionEntry();
    when(existingRegionEntry.isDestroyedOrRemoved()).thenReturn(true);
  }

  private void givenFactoryRegionEntry() {
    when(entryMap.get(eq(key))).thenReturn(null);
    when(regionEntryFactory.createEntry(any(), any(), any())).thenReturn(factoryRegionEntry);
  }

  private void givenOldRegionEntry() {
    when(entryMap.get(eq(key))).thenReturn(null);
    when(regionEntryFactory.createEntry(any(), any(), any())).thenReturn(factoryRegionEntry);
    when(entryMap.putIfAbsent(eq(key), same(factoryRegionEntry))).thenReturn(oldRegionEntry);
  }

  private void givenOldRemovedRegionEntry() {
    givenOldRegionEntry();
    when(oldRegionEntry.isDestroyedOrRemoved()).thenReturn(true);
  }

  private void givenNotInTokenMode() {
    inTokenMode = false;
  }

  private void givenConcurrencyChecks() {
    when(owner.getConcurrencyChecksEnabled()).thenReturn(true);
    when(partitionedRegion.getConcurrencyChecksEnabled()).thenReturn(true);
  }

  private void givenNoConcurrencyChecks() {
    when(owner.getConcurrencyChecksEnabled()).thenReturn(false);
  }

  private void givenLocalRegion() {
    owner = mock(LocalRegion.class);
    setupLocalRegion();
    regionMap = spy(new TestableAbstractRegionMap());
  }

  private void givenBucketRegion() {
    BucketRegion bucketRegion = mock(BucketRegion.class);
    when(bucketRegion.isUsedForPartitionedRegionBucket()).thenReturn(true);
    when(bucketRegion.getPartitionedRegion()).thenReturn(partitionedRegion);
    when(bucketRegion.getBucketAdvisor()).thenReturn(mock(BucketAdvisor.class));
    owner = bucketRegion;
    setupLocalRegion();
    regionMap = spy(new TestableAbstractRegionMap());
  }

  private void setupLocalRegion() {

    InternalCache cache = mock(InternalCache.class);
    InternalDistributedSystem ids = mock(InternalDistributedSystem.class);
    when(owner.getCachePerfStats()).thenReturn(cachePerfStats);
    when(owner.getCache()).thenReturn(cache);
    when(owner.getMyId()).thenReturn(myId);
    when(owner.getKeyInfo(any(), any(), any())).thenReturn(keyInfo);
    when(cache.getDistributedSystem()).thenReturn(ids);
    when(ids.getOffHeapStore()).thenReturn(null);
  }

  private void doTxApplyDestroy() {
    regionMap.txApplyDestroy(key, txId, txEvent, inTokenMode, inRI, operation, eventId,
        aCallbackArgument, pendingCallbacks, filterRoutingInfo, bridgeContext, isOriginRemote,
        txEntryState, versionTag, tailKey);
  }

  private class TestableAbstractRegionMap extends AbstractRegionMap {

    TestableAbstractRegionMap() {
      super(null);
      initialize(owner, new Attributes(), null, false);
      setEntryMap(entryMap);
      setEntryFactory(regionEntryFactory);
    }

  }
}


text:
from __future__ import absolute_import, unicode_literals

__version__ = '0.8.0'

redpajama_set_name: RedPajamaGithub


text:
<?php

class CControllerMapView extends CController {

	private $sysmapid;

	protected function init() {
		$this->disableSIDValidation();
	}

	protected function checkInput() {
		$fields = [
			'sysmapid' =>		'db sysmaps.sysmapid',
			'mapname' =>		'not_empty',
			'severity_min' =>	'in 0,1,2,3,4,5',
			'fullscreen' =>		'in 0,1'
		];

		$ret = $this->validateInput($fields);

		if (!$ret) {
			$this->setResponse(new CControllerResponseFatal());
		}

		return $ret;
	}

	protected function checkPermissions() {
		if ($this->getUserType() < USER_TYPE_ZABBIX_USER) {
			return false;
		}

		$sysmapid = null;
		$options = ['output' => ['sysmapid']];

		if ($this->hasInput('mapname')) {
			// Get map by name.
			$options['search']['name'] = $this->getInput('mapname');
		}
		elseif ($this->hasInput('sysmapid')) {
			// Get map by sysmapid from request.
			$options['sysmapids'] = [$this->getInput('sysmapid')];
		}
		else {
			// Get map by sysmapid from profile.
			$options['sysmapids'] = [CProfile::get('web.maps.sysmapid', 0)];
		}

		$sysmaps = API::Map()->get($options);

		if ($sysmaps) {
			$sysmap = reset($sysmaps);
			$sysmapid = $sysmap['sysmapid'];
		}

		if ($sysmapid === null) {
			if (!$this->hasInput('mapname') && !$this->hasInput('sysmapid')) {
				// Redirect to map list.
				redirect('sysmaps.php');
			}
			else {
				// No permissions.
				return false;
			}
		}

		$this->sysmapid = $sysmapid;

		return true;
	}

	protected function doAction() {
		CProfile::update('web.maps.sysmapid', $this->sysmapid, PROFILE_TYPE_ID);

		$data = [
			'fullscreen' => $this->getInput('fullscreen', 0)
		];

		$maps = API::Map()->get([
			'output' => ['name', 'severity_min'],
			'sysmapids' => [$this->sysmapid]
		]);
		$data['map'] = reset($maps);

		$data['map']['editable'] = API::Map()->isWritable([$this->sysmapid]);

		$data['pageFilter'] = new CPageFilter([
			'severitiesMin' => [
				'default' => $data['map']['severity_min'],
				'mapId' => $this->sysmapid
			],
			'severityMin' => $this->hasInput('severity_min') ? $this->getInput('severity_min') : null
		]);

		$data['severity_min'] = $data['pageFilter']->severityMin;

		$response = new CControllerResponseData($data);
		$response->setTitle(_('Network maps'));
		$this->setResponse($response);
	}
}


text:
#ifndef _Aruco_CameraParameters_H
#define  _Aruco_CameraParameters_H
#include "exports.h"
#include <opencv2/opencv.hpp>
#include <string>
using namespace std;
namespace aruco
{
/**\brief Parameters of the camera
 */

class ARUCO_EXPORTS  CameraParameters
{
public:

    // 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1)
    cv::Mat  CameraMatrix;
    //4x1 matrix (k1,k2,p1,p2)
    cv::Mat  Distorsion;
    //size of the image
    cv::Size CamSize;

    /**Empty constructor
     */
    CameraParameters() ;
    /**Creates the object from the info passed
     * @param cameraMatrix 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1)
     * @param distorsionCoeff 4x1 matrix (k1,k2,p1,p2)
     * @param size image size
     */
    CameraParameters(cv::Mat cameraMatrix,cv::Mat distorsionCoeff,cv::Size size) throw(cv::Exception);
    /**Sets the parameters
     * @param cameraMatrix 3x3 matrix (fx 0 cx, 0 fy cy, 0 0 1)
     * @param distorsionCoeff 4x1 matrix (k1,k2,p1,p2)
     * @param size image size
     */
    void setParams(cv::Mat cameraMatrix,cv::Mat distorsionCoeff,cv::Size size) throw(cv::Exception);
    /**Copy constructor
     */
    CameraParameters(const CameraParameters &CI) ;

    /**Indicates whether this object is valid
     */
    bool isValid()const {
        return CameraMatrix.rows!=0 && CameraMatrix.cols!=0  && Distorsion.rows!=0 && Distorsion.cols!=0 && CamSize.width!=-1 && CamSize.height!=-1;
    }
    /**Assign operator
    */
    CameraParameters & operator=(const CameraParameters &CI);
    /**Reads the camera parameters from a file generated using saveToFile.
     */
    void readFromFile(string path)throw(cv::Exception);
    /**Saves this to a file
     */
    void saveToFile(string path,bool inXML=true)throw(cv::Exception);

    /**Reads from a YAML file generated with the opencv2.2 calibration utility
     */
    void readFromXMLFile(string filePath)throw(cv::Exception);

    /**Adjust the parameters to the size of the image indicated
     */
    void resize(cv::Size size)throw(cv::Exception);

    /**Returns the location of the camera in the reference system given by the rotation and translation vectors passed
     * NOT TESTED
    */
    static cv::Point3f getCameraLocation(cv::Mat Rvec,cv::Mat Tvec);

    /**Given the intrinsic camera parameters returns the GL_PROJECTION matrix for opengl.
    * PLease NOTE that when using OpenGL, it is assumed no camera distorsion! So, if it is not true, you should have
    * undistor image
    *
    * @param orgImgSize size of the original image
    * @param size of the image/window where to render (can be different from the real camera image). Please not that it must be related to CamMatrix
    * @param proj_matrix output projection matrix to give to opengl
    * @param gnear,gfar: visible rendering range
    * @param invert: indicates if the output projection matrix has to yield a horizontally inverted image because image data has not been stored in the order of glDrawPixels: bottom-to-top.
    */
    void glGetProjectionMatrix( cv::Size orgImgSize, cv::Size size,float proj_matrix[16],float gnear,float gfar,bool invert=false   )throw(cv::Exception);

    /**
     * setup camera for an Ogre project.
     * 	Use:
     * ...
     * Ogre::Matrix4 PM(proj_matrix[0], proj_matrix[1], ... , proj_matrix[15]);
     * yourCamera->setCustomProjectionMatrix(true, PM);
     * yourCamera->setCustomViewMatrix(true, Ogre::Matrix4::IDENTITY);
     * ...
     * As in OpenGL, it assumes no camera distorsion
     */
    void OgreGetProjectionMatrix( cv::Size orgImgSize, cv::Size size,float proj_matrix[16],float gnear,float gfar,bool invert=false   )throw(cv::Exception);

private:
    //GL routines

    static void argConvGLcpara2( float cparam[3][4], int width, int height, float gnear, float gfar, float m[16], bool invert )throw(cv::Exception);
    static int  arParamDecompMat( float source[3][4], float cpara[3][4], float trans[3][4] )throw(cv::Exception);
    static float norm( float a, float b, float c );
    static float dot(  float a1, float a2, float a3,
                        float b1, float b2, float b3 );

};

}
#endif


text:
namespace caf::detail {

template <class T>
bool cas_weak(std::atomic<T>* obj, T* expected, T desired) {
#if (defined(CAF_CLANG) && CAF_COMPILER_VERSION < 30401)                       \
  || (defined(CAF_GCC) && CAF_COMPILER_VERSION < 40803)
  return std::atomic_compare_exchange_strong(obj, expected, desired);
#else
  return std::atomic_compare_exchange_weak(obj, expected, desired);
#endif
}

} // namespace caf::detail


text:
using Commanding.Modules.Order.Views;
using Commanding.Modules.Order.Services;
using Microsoft.Practices.Unity;
using Prism.Modularity;
using Prism.Regions;

namespace Commanding.Modules.Order
{
    public class OrderModule : IModule
    {
        private readonly IRegionManager  regionManager;
        private readonly IUnityContainer container;

        public OrderModule( IUnityContainer container, IRegionManager regionManager )
        {
            this.container     = container;
            this.regionManager = regionManager;
        }

        public void Initialize()
        {
            this.container.RegisterType<IOrdersRepository, OrdersRepository>(new ContainerControlledLifetimeManager());

            // Show the Orders Editor view in the shell's main region.
            this.regionManager.RegisterViewWithRegion( "MainRegion",
                                                       () => this.container.Resolve<OrdersEditorView>() );

            // Show the Orders Toolbar view in the shell's toolbar region.
            this.regionManager.RegisterViewWithRegion( "GlobalCommandsRegion",
                                                       () => this.container.Resolve<OrdersToolBar>() );
        }
    }
}


text:
// -----------------------------------------------------------------------
// Copyright (c) VoidSt4r. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// -----------------------------------------------------------------------

namespace Diablo2FileFormat.Interfaces
{
    public interface IQuestData
    {
        /// <summary>
        /// Changes the completion state of a specific quest.
        /// </summary>
        /// <param name="difficulty">The quest difficulty.</param>
        /// <param name="act">The quest act.</param>
        /// <param name="quest">The specific quest.</param>
        /// <param name="complete">Quest completion state.</param>
        void ChangeQuest(Difficulty difficulty, Act act, Quest quest, bool complete);

        /// <summary>
        /// Changes all quest completion states of a specific act.
        /// </summary>
        /// <param name="difficulty">The quest difficulty.</param>
        /// <param name="act">The quest act.</param>
        /// <param name="complete">Quest completion state.</param>
        void ChangeQuests(Difficulty difficulty, Act act, bool complete);

        /// <summary>
        /// Changes all quest completion states of a specific difficulty.
        /// </summary>
        /// <param name="difficulty">The quest difficulty.</param>
        /// <param name="complete">Quest completion state.</param>
        void ChangeQuests(Difficulty difficulty, bool complete);

        /// <summary>
        /// Changes all quest completion states.
        /// </summary>
        /// <param name="complete">Quest completion state.</param>
        void ChangeQuests(bool complete);
    }
}


text: module.exports = [{"isClass":true,"priority":10000.0066,"key":"container","style":{}}];


text:
package org.intellij.plugins.relaxNG.model.resolve;

import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.navigation.ColoredItemPresentation;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.NavigationItem;
import com.intellij.navigation.PsiElementNavigationItem;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.meta.PsiPresentableMetaData;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.indexing.*;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.xml.NanoXmlUtil;
import org.intellij.plugins.relaxNG.ApplicationLoader;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.model.CommonElement;
import org.intellij.plugins.relaxNG.model.Define;
import org.intellij.plugins.relaxNG.model.Grammar;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.*;

public class RelaxSymbolIndex extends ScalarIndexExtension<String> {
  @NonNls
  public static final ID<String, Void> NAME = ID.create("RelaxSymbolIndex");

  public static Collection<String> getSymbolNames(Project project) {
    return FileBasedIndex.getInstance().getAllKeys(NAME, project);
  }

  public static NavigationItem[] getSymbolsByName(final String name, Project project, boolean includeNonProjectItems) {
    final GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
    final Collection<NavigationItem> result = new ArrayList<>();
    PsiManager psiManager = PsiManager.getInstance(project);

    for(VirtualFile file:FileBasedIndex.getInstance().getContainingFiles(NAME, name, scope)) {
      final PsiFile psiFile = psiManager.findFile(file);

      if (psiFile instanceof XmlFile) {
        final Grammar grammar = GrammarFactory.getGrammar((XmlFile)psiFile);

        if (grammar != null) {
          grammar.acceptChildren(new CommonElement.Visitor() {
            @Override
            public void visitDefine(Define define) {
              if (name.equals(define.getName())) {
                final PsiElement psi = define.getPsiElement();
                if (psi != null) {
                  MyNavigationItem.add((NavigationItem)define.getPsiElement(), result);
                }
              }
            }
          });
        }
      }
    }
    return result.toArray(NavigationItem.EMPTY_NAVIGATION_ITEM_ARRAY);
  }

  @NotNull
  @Override
  public ID<String, Void> getName() {
    return NAME;
  }

  @NotNull
  @Override
  public DataIndexer<String, Void, FileContent> getIndexer() {
    return new DataIndexer<String, Void, FileContent>() {
      @Override
      @NotNull
      public Map<String, Void> map(@NotNull FileContent inputData) {
        final HashMap<String, Void> map = new HashMap<>();
        if (inputData.getFileType() == XmlFileType.INSTANCE) {
          CharSequence inputDataContentAsText = inputData.getContentAsText();
          if (CharArrayUtil.indexOf(inputDataContentAsText, ApplicationLoader.RNG_NAMESPACE, 0) == -1) return Collections.emptyMap();
          NanoXmlUtil.parse(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()), new NanoXmlUtil.IXMLBuilderAdapter() {
            NanoXmlUtil.IXMLBuilderAdapter attributeHandler;
            int depth;

            @Override
            public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
              if (attributeHandler != null) {
                attributeHandler.addAttribute(key, nsPrefix, nsURI, value, type);
              }
            }

            @Override
            public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) throws Exception {
              attributeHandler = null;
              if (depth == 1 && ApplicationLoader.RNG_NAMESPACE.equals(nsURI)) {
                if ("define".equals(name)) {
                  attributeHandler = new NanoXmlUtil.IXMLBuilderAdapter() {
                    @Override
                    public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
                      if ("name".equals(key) && (nsURI == null || nsURI.length() == 0) && value != null) {
                        map.put(value, null);
                      }
                    }
                  };
                }
              }
              depth++;
            }

            @Override
            public void endElement(String name, String nsPrefix, String nsURI) throws Exception {
              attributeHandler = null;
              depth--;
            }
          });
        } else if (inputData.getFileType() == RncFileType.getInstance()) {
          final PsiFile file = inputData.getPsiFile();
          if (file instanceof XmlFile) {
            final Grammar grammar = GrammarFactory.getGrammar((XmlFile)file);
            if (grammar != null) {
              grammar.acceptChildren(new CommonElement.Visitor() {
                @Override
                public void visitDefine(Define define) {
                  final String name = define.getName();
                  if (name != null) {
                    map.put(name, null);
                  }
                }
              });
            }
          }
        }
        return map;
      }
    };
  }

  @NotNull
  @Override
  public KeyDescriptor<String> getKeyDescriptor() {
    return EnumeratorStringDescriptor.INSTANCE;
  }

  @NotNull
  @Override
  public FileBasedIndex.InputFilter getInputFilter() {
    return new DefaultFileTypeSpecificInputFilter(StdFileTypes.XML, RncFileType.getInstance()) {
      @Override
      public boolean acceptInput(@NotNull VirtualFile file) {
        return !(file.getFileSystem() instanceof JarFileSystem);
      }
    };
  }

  @Override
  public boolean dependsOnFileContent() {
    return true;
  }

  @Override
  public int getVersion() {
    return 0;
  }

  private static class MyNavigationItem implements PsiElementNavigationItem, ItemPresentation {
    private final NavigationItem myItem;
    private final ItemPresentation myPresentation;

    private MyNavigationItem(NavigationItem item, @NotNull final ItemPresentation presentation) {
      myItem = item;
      myPresentation = presentation;
    }

    @Override
    public String getPresentableText() {
      return myPresentation.getPresentableText();
    }

    @Override
    @Nullable
    public String getLocationString() {
      return getLocationString((PsiElement)myItem);
    }

    private static String getLocationString(PsiElement element) {
      return "(in " + element.getContainingFile().getName() + ")";
    }

    @Override
    @Nullable
    public Icon getIcon(boolean open) {
      return myPresentation.getIcon(open);
    }

    @Nullable
    public TextAttributesKey getTextAttributesKey() {
      return myPresentation instanceof ColoredItemPresentation ? ((ColoredItemPresentation) myPresentation).getTextAttributesKey() : null;
    }

    @Override
    public String getName() {
      return myItem.getName();
    }

    @Override
    public ItemPresentation getPresentation() {
      return this;
    }

    @Override
    public PsiElement getTargetElement() {
      return (PsiElement) myItem;
    }

    @Override
    public void navigate(boolean requestFocus) {
      myItem.navigate(requestFocus);
    }

    @Override
    public boolean canNavigate() {
      return myItem.canNavigate();
    }

    @Override
    public boolean canNavigateToSource() {
      return myItem.canNavigateToSource();
    }

    public static void add(final NavigationItem item, Collection<NavigationItem> symbolNavItems) {
      final ItemPresentation presentation;
      if (item instanceof PsiMetaOwner) {
        final PsiMetaData data = ((PsiMetaOwner)item).getMetaData();
        if (data instanceof PsiPresentableMetaData) {
          final PsiPresentableMetaData metaData = (PsiPresentableMetaData)data;
          presentation = new ColoredItemPresentation() {
            @Override
            public String getPresentableText() {
              return metaData.getName();
            }

            @Override
            @Nullable
            public String getLocationString() {
              return MyNavigationItem.getLocationString((PsiElement)item);
            }

            @Override
            @Nullable
            public Icon getIcon(boolean open) {
              return metaData.getIcon();
            }

            @Nullable
            @Override
            public TextAttributesKey getTextAttributesKey() {
              final ItemPresentation p = item.getPresentation();
              return p instanceof ColoredItemPresentation ? ((ColoredItemPresentation) p).getTextAttributesKey() : null;
            }
          };
        } else {
          presentation = item.getPresentation();
        }
      } else {
        presentation = item.getPresentation();
      }

      if (presentation != null) {
        symbolNavItems.add(new MyNavigationItem(item, presentation));
      }
    }
  }
}


text:
<?php
namespace examples;

/**
 * @some value
*/
class SomeClass {

	/**
	 * @DefaultValue1("value1")
	 * @DefaultValue2("value2")
	 */
	public function __construct($value1 = null, $value2 = null) {

	}

	/**
	 * @single("value")
	 * @array(["v1","v2"])
	 * @multiple({"int":1,"string":"foo"})
	 * @without
	 */
	public function method1() {
		// do something
	}

	/**
	 * @SomeString("parameter1")
	 * @SomeOtherString("parameter2")
	 */
	public function method2($parameter1, $parameter2) {

	}

}

?>