@Override
  public boolean process(String type, String message, Object object) {
    Applications applications = (Applications) object;

    if (GroupInstanceTerminatingEvent.class.getName().equals(type)) {
      // Return if applications has not been initialized
      if (!applications.isInitialized()) return false;

      // Parse complete message and build event
      GroupInstanceTerminatingEvent event =
          (GroupInstanceTerminatingEvent)
              MessagingUtil.jsonToObject(message, GroupInstanceTerminatingEvent.class);

      ApplicationsUpdater.acquireWriteLockForApplication(event.getAppId());

      try {
        return doProcess(event, applications);

      } finally {
        ApplicationsUpdater.releaseWriteLockForApplication(event.getAppId());
      }

    } else {
      if (nextProcessor != null) {
        // ask the next processor to take care of the message.
        return nextProcessor.process(type, message, applications);
      } else {
        throw new RuntimeException(
            String.format(
                "Failed to process message using available message processors: [type] %s [body] %s",
                type, message));
      }
    }
  }
  @Override
  public boolean process(String type, String message, Object object) {
    Topology topology = (Topology) object;

    if (MemberMaintenanceModeEvent.class.getName().equals(type)) {
      // Return if topology has not been initialized
      if (!TopologyManager.isInitialized()) return false;

      // Parse complete message and build event
      MemberMaintenanceModeEvent event =
          (MemberMaintenanceModeEvent)
              MessagingUtil.jsonToObject(message, MemberMaintenanceModeEvent.class);

      TopologyUpdater.acquireWriteLockForCluster(event.getServiceName(), event.getClusterId());
      try {
        return doProcess(event, topology);

      } finally {
        TopologyUpdater.releaseWriteLockForCluster(event.getServiceName(), event.getClusterId());
      }

    } else {
      if (nextProcessor != null) {
        // ask the next processor to take care of the message.
        return nextProcessor.process(type, message, topology);
      } else {
        throw new RuntimeException(
            String.format(
                "Failed to process message using available message processors: [type] %s [body] %s",
                type, message));
      }
    }
  }
  @Override
  public boolean process(String type, String message, Object object) {
    if (InstanceCleanupMemberEvent.class.getName().equals(type)) {
      // Parse complete message and build event
      InstanceCleanupMemberEvent event =
          (InstanceCleanupMemberEvent) Util.jsonToObject(message, InstanceCleanupMemberEvent.class);

      // Notify event listeners
      notifyEventListeners(event);
      return true;
    } else {
      if (nextProcessor != null) {
        return nextProcessor.process(type, message, object);
      } else {
        throw new RuntimeException(
            String.format(
                "Failed to process instance clean up using available message processors: [type] %s [body] %s",
                type, message));
      }
    }
  }
  @Override
  public boolean process(String type, String message, Object object) {
    if (CompleteTopologyRequestEvent.class.getName().equals(type)) {
      // Parse complete message and build event
      CompleteTopologyRequestEvent event =
          (CompleteTopologyRequestEvent)
              MessagingUtil.jsonToObject(message, CompleteTopologyRequestEvent.class);

      // Notify event listeners
      notifyEventListeners(event);
      return true;
    } else {
      if (nextProcessor != null) {
        // ask the next processor to take care of the message.
        return nextProcessor.process(type, message, object);
      } else {
        throw new RuntimeException(
            String.format(
                "Failed to process message using available message processors: [type] %s [body] %s",
                type, message));
      }
    }
  }
  @Override
  public boolean process(String type, String message, Object object) {
    Topology topology = (Topology) object;

    if (MemberTerminatedEvent.class.getName().equals(type)) {
      // Return if topology has not been initialized
      if (!topology.isInitialized()) return false;

      // Parse complete message and build event
      MemberTerminatedEvent event =
          (MemberTerminatedEvent) Util.jsonToObject(message, MemberTerminatedEvent.class);

      // Apply service filter
      if (TopologyServiceFilter.getInstance().isActive()) {
        if (TopologyServiceFilter.getInstance().serviceNameExcluded(event.getServiceName())) {
          // Service is excluded, do not update topology or fire event
          if (log.isDebugEnabled()) {
            log.debug(String.format("Service is excluded: [service] %s", event.getServiceName()));
          }
          return false;
        }
      }

      // Apply cluster filter
      if (TopologyClusterFilter.getInstance().isActive()) {
        if (TopologyClusterFilter.getInstance().clusterIdExcluded(event.getClusterId())) {
          // Cluster is excluded, do not update topology or fire event
          if (log.isDebugEnabled()) {
            log.debug(String.format("Cluster is excluded: [cluster] %s", event.getClusterId()));
          }
          return false;
        }
      }

      // Validate event against the existing topology
      Service service = topology.getService(event.getServiceName());
      if (service == null) {
        if (log.isWarnEnabled()) {
          log.warn(String.format("Service does not exist: [service] %s", event.getServiceName()));
        }
        return false;
      }
      Cluster cluster = service.getCluster(event.getClusterId());
      if (cluster == null) {
        if (log.isWarnEnabled()) {
          log.warn(
              String.format(
                  "Cluster does not exist: [service] %s [cluster] %s",
                  event.getServiceName(), event.getClusterId()));
        }
        return false;
      }
      Member member = cluster.getMember(event.getMemberId());
      if (member == null) {
        if (log.isWarnEnabled()) {
          log.warn(
              String.format(
                  "Member does not exist: [service] %s [cluster] %s [member] %s",
                  event.getServiceName(), event.getClusterId(), event.getMemberId()));
        }
        return false;
      }

      // Apply member filter
      if (TopologyMemberFilter.getInstance().isActive()) {
        if (TopologyMemberFilter.getInstance().lbClusterIdExcluded(member.getLbClusterId())) {
          if (log.isDebugEnabled()) {
            log.debug(
                String.format("Member is excluded: [lb-cluster-id] %s", member.getLbClusterId()));
          }
          return false;
        }
      }

      if (member.getStatus() == MemberStatus.Terminated) {
        if (log.isWarnEnabled()) {
          log.warn(
              String.format(
                  "Member already terminated: [service] %s [cluster] %s [member] %s",
                  event.getServiceName(), event.getClusterId(), event.getMemberId()));
        }
      } else {

        // Apply changes to the topology
        member.setStatus(MemberStatus.Terminated);
        // removing the member from the cluster
        cluster.removeMember(member);

        if (log.isInfoEnabled()) {
          log.info(
              String.format(
                  "Member terminated: [service] %s [cluster] %s [member] %s",
                  event.getServiceName(), event.getClusterId(), event.getMemberId()));
        }
      }

      notifyEventListeners(event);
      return true;

    } else {
      if (nextProcessor != null) {
        // ask the next processor to take care of the message.
        return nextProcessor.process(type, message, topology);
      } else {
        throw new RuntimeException(
            String.format(
                "Failed to process message using available message processors: [type] %s [body] %s",
                type, message));
      }
    }
  }