Moved some event waiting code to lang so that it can be used in other
services.
diff --git a/service/src/main/java/io/mifos/provisioner/internal/listener/EventExpectation.java b/service/src/main/java/io/mifos/provisioner/internal/listener/EventExpectation.java
deleted file mode 100644
index 23d0e99..0000000
--- a/service/src/main/java/io/mifos/provisioner/internal/listener/EventExpectation.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2017 The Mifos Initiative.
- *
- * 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
- *
- *    http://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 io.mifos.provisioner.internal.listener;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * @author Myrle Krantz
- */
-public class EventExpectation {
-  private final EventKey key;
-  private boolean eventFound = false;
-  private boolean eventWithdrawn = false;
-
-  private final ReentrantLock lock = new ReentrantLock();
-
-  private final Condition found = lock.newCondition();
-
-  EventExpectation(final EventKey key) {
-    this.key = key;
-  }
-
-  EventKey getKey() {
-    return key;
-  }
-
-  void setEventFound(boolean eventFound) {
-    lock.lock();
-    try {
-      this.eventFound = eventFound;
-      found.signal();
-    }
-    finally {
-      lock.unlock();
-    }
-  }
-
-  void setEventWithdrawn(boolean eventWithdrawn) {
-    lock.lock();
-    try {
-      this.eventWithdrawn = eventWithdrawn;
-      found.signal();
-    }
-    finally {
-      lock.unlock();
-    }
-  }
-
-  public boolean waitForOccurrence(long timeout, TimeUnit timeUnit) throws InterruptedException {
-
-    lock.lock();
-    try {
-      if (eventFound)
-      return true;
-
-      if (eventWithdrawn)
-        return false;
-
-      found.await(timeout, timeUnit);
-
-      return (eventFound);
-    }
-    finally {
-      lock.unlock();
-    }
-  }
-
-  @Override
-  public String toString() {
-    return key.toString();
-  }
-}
diff --git a/service/src/main/java/io/mifos/provisioner/internal/listener/EventKey.java b/service/src/main/java/io/mifos/provisioner/internal/listener/EventKey.java
deleted file mode 100644
index 13f985e..0000000
--- a/service/src/main/java/io/mifos/provisioner/internal/listener/EventKey.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2017 The Mifos Initiative.
- *
- * 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
- *
- *    http://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 io.mifos.provisioner.internal.listener;
-
-import java.util.Objects;
-
-/**
- * @author Myrle Krantz
- */
-class EventKey {
-  private String tenantIdentifier;
-  private String eventName;
-  private Object event;
-
-  EventKey(final String tenantIdentifier, final String eventName, final Object event) {
-    this.tenantIdentifier = tenantIdentifier;
-    this.eventName = eventName;
-    this.event = event;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-    EventKey eventKey = (EventKey) o;
-    return Objects.equals(tenantIdentifier, eventKey.tenantIdentifier) &&
-            Objects.equals(eventName, eventKey.eventName) &&
-            Objects.equals(event, eventKey.event);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(tenantIdentifier, eventName, event);
-  }
-
-  @Override
-  public String toString() {
-    return "EventKey{" +
-            "tenantIdentifier='" + tenantIdentifier + '\'' +
-            ", eventName='" + eventName + '\'' +
-            ", event=" + event +
-            '}';
-  }
-}
diff --git a/service/src/main/java/io/mifos/provisioner/internal/listener/IdentityListener.java b/service/src/main/java/io/mifos/provisioner/internal/listener/IdentityListener.java
index fb4d638..e0f988a 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/listener/IdentityListener.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/listener/IdentityListener.java
@@ -17,7 +17,9 @@
 
 import com.google.gson.Gson;
 import io.mifos.core.lang.config.TenantHeaderFilter;
-import io.mifos.identity.api.v1.events.ApplicationPermissionEvent;
+import io.mifos.core.lang.listening.EventExpectation;
+import io.mifos.core.lang.listening.EventKey;
+import io.mifos.core.lang.listening.TenantedEventListener;
 import io.mifos.identity.api.v1.events.ApplicationSignatureEvent;
 import io.mifos.identity.api.v1.events.EventConstants;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -25,10 +27,6 @@
 import org.springframework.messaging.handler.annotation.Header;
 import org.springframework.stereotype.Component;
 
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static io.mifos.identity.api.v1.events.EventConstants.OPERATION_POST_APPLICATION_PERMISSION;
 import static io.mifos.identity.api.v1.events.EventConstants.OPERATION_POST_PERMITTABLE_GROUP;
 import static io.mifos.identity.api.v1.events.EventConstants.OPERATION_PUT_APPLICATION_SIGNATURE;
 
@@ -38,7 +36,7 @@
 @Component
 public class IdentityListener {
   private final Gson gson;
-  private final Map<EventKey, EventExpectation> eventExpectations = new ConcurrentHashMap<>();
+  private final TenantedEventListener eventListener = new TenantedEventListener();
 
   @Autowired
   public IdentityListener(final Gson gson) {
@@ -53,25 +51,7 @@
   public void onCreatePermittableGroup(
           @Header(TenantHeaderFilter.TENANT_HEADER)final String tenantIdentifier,
           final String payload) throws Exception {
-    final EventExpectation eventExpectation = eventExpectations.remove(new EventKey(tenantIdentifier, OPERATION_POST_PERMITTABLE_GROUP, payload));
-    if (eventExpectation != null) {
-      eventExpectation.setEventFound(true);
-    }
-  }
-
-  @JmsListener(
-          subscription = EventConstants.DESTINATION,
-          destination = EventConstants.DESTINATION,
-          selector = EventConstants.SELECTOR_POST_APPLICATION_PERMISSION
-  )
-  public void onCreateApplicationPermission(
-          @Header(TenantHeaderFilter.TENANT_HEADER)final String tenantIdentifier,
-          final String payload) throws Exception {
-    final ApplicationPermissionEvent event = gson.fromJson(payload, ApplicationPermissionEvent.class);
-    final EventExpectation eventExpectation = eventExpectations.remove(new EventKey(tenantIdentifier, OPERATION_POST_APPLICATION_PERMISSION, event));
-    if (eventExpectation != null) {
-      eventExpectation.setEventFound(true);
-    }
+    eventListener.notify(new EventKey(tenantIdentifier, OPERATION_POST_PERMITTABLE_GROUP, payload));
   }
 
   @JmsListener(
@@ -83,44 +63,22 @@
           @Header(TenantHeaderFilter.TENANT_HEADER)final String tenantIdentifier,
           final String payload) throws Exception {
     final ApplicationSignatureEvent event = gson.fromJson(payload, ApplicationSignatureEvent.class);
-    final EventExpectation eventExpectation = eventExpectations.remove(new EventKey(tenantIdentifier, OPERATION_PUT_APPLICATION_SIGNATURE, event));
-    if (eventExpectation != null) {
-      eventExpectation.setEventFound(true);
-    }
+    eventListener.notify(new EventKey(tenantIdentifier, OPERATION_PUT_APPLICATION_SIGNATURE, event));
   }
 
   public EventExpectation expectPermittableGroupCreation(final String tenantIdentifier,
                                                          final String permittableGroupIdentifier) {
-    final EventKey key = new EventKey(tenantIdentifier, OPERATION_POST_PERMITTABLE_GROUP, permittableGroupIdentifier);
-    final EventExpectation value = new EventExpectation(key);
-    eventExpectations.put(key, value);
-    return value;
-  }
-
-  public EventExpectation expectApplicationPermissionCreation(final String tenantIdentifier,
-                                                              final String applicationIdentifier,
-                                                              final String permittableGroupIdentifier) {
-    final ApplicationPermissionEvent expectedEvent = new ApplicationPermissionEvent(applicationIdentifier, permittableGroupIdentifier);
-    final EventKey key = new EventKey(tenantIdentifier, OPERATION_POST_APPLICATION_PERMISSION, expectedEvent);
-    final EventExpectation value = new EventExpectation(key);
-    eventExpectations.put(key, value);
-    return value;
+    return eventListener.expect(new EventKey(tenantIdentifier, OPERATION_POST_PERMITTABLE_GROUP, permittableGroupIdentifier));
   }
 
   public EventExpectation expectApplicationSignatureSet(final String tenantIdentifier,
                                                         final String applicationIdentifier,
                                                         final String keyTimestamp) {
     final ApplicationSignatureEvent expectedEvent = new ApplicationSignatureEvent(applicationIdentifier, keyTimestamp);
-    final EventKey key = new EventKey(tenantIdentifier, OPERATION_PUT_APPLICATION_SIGNATURE, expectedEvent);
-    final EventExpectation value = new EventExpectation(key);
-    eventExpectations.put(key, value);
-    return value;
+    return eventListener.expect(new EventKey(tenantIdentifier, OPERATION_PUT_APPLICATION_SIGNATURE, expectedEvent));
   }
 
   public void withdrawExpectation(final EventExpectation eventExpectation) {
-    final EventExpectation expectation = eventExpectations.remove(eventExpectation.getKey());
-    if (expectation != null) {
-      eventExpectation.setEventWithdrawn(true);
-    }
+    eventListener.withdrawExpectation(eventExpectation);
   }
-}
+}
\ No newline at end of file
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java b/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java
index 2e45d9c..fe900c7 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java
@@ -23,8 +23,8 @@
 import io.mifos.core.cassandra.core.CassandraSessionProvider;
 import io.mifos.core.lang.AutoTenantContext;
 import io.mifos.core.lang.ServiceException;
+import io.mifos.core.lang.listening.EventExpectation;
 import io.mifos.provisioner.config.ProvisionerConstants;
-import io.mifos.provisioner.internal.listener.EventExpectation;
 import io.mifos.provisioner.internal.repository.ApplicationEntity;
 import io.mifos.provisioner.internal.repository.TenantApplicationEntity;
 import io.mifos.provisioner.internal.repository.TenantCassandraRepository;
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java b/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
index bb1f104..83b5de1 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
@@ -23,6 +23,7 @@
 import io.mifos.core.api.util.InvalidTokenException;
 import io.mifos.core.lang.ServiceException;
 import io.mifos.core.lang.TenantContextHolder;
+import io.mifos.core.lang.listening.EventExpectation;
 import io.mifos.identity.api.v1.client.ApplicationPermissionAlreadyExistsException;
 import io.mifos.identity.api.v1.client.CallEndpointSetAlreadyExistsException;
 import io.mifos.identity.api.v1.client.IdentityManager;
@@ -34,7 +35,6 @@
 import io.mifos.permittedfeignclient.api.v1.domain.ApplicationPermission;
 import io.mifos.provisioner.config.ProvisionerConstants;
 import io.mifos.provisioner.config.SystemProperties;
-import io.mifos.provisioner.internal.listener.EventExpectation;
 import io.mifos.provisioner.internal.listener.IdentityListener;
 import io.mifos.tool.crypto.HashGenerator;
 import org.slf4j.Logger;