gt:                 if (idx >= 0) {
context: /**
   * Copyright (c) 2010-2020 Contributors to the openHAB project
   *
   * See the NOTICE file(s) distributed with this work for additional
   * information.
   *
   * This program and the accompanying materials are made available under the
   * terms of the Eclipse Public License 2.0 which is available at
   * http://www.eclipse.org/legal/epl-2.0
   *
   * SPDX-License-Identifier: EPL-2.0
   */
  package org.openhab.io.neeo.internal.discovery;
  
  import java.io.File;
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.UnknownHostException;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.util.AbstractMap;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Objects;
  import java.util.Optional;
  import java.util.concurrent.ScheduledExecutorService;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.locks.Lock;
  import java.util.concurrent.locks.ReentrantLock;
  import java.util.stream.Collectors;
  
  import javax.jmdns.ServiceEvent;
  import javax.jmdns.ServiceInfo;
  import javax.jmdns.ServiceListener;
  import javax.ws.rs.client.ClientBuilder;
  
  import org.apache.commons.lang.StringUtils;
  import org.eclipse.jdt.annotation.NonNullByDefault;
  import org.eclipse.jdt.annotation.Nullable;
  import org.openhab.core.common.ThreadPoolManager;
  import org.openhab.core.io.transport.mdns.MDNSClient;
  import org.openhab.io.neeo.internal.NeeoApi;
  import org.openhab.io.neeo.internal.NeeoConstants;
  import org.openhab.io.neeo.internal.NeeoUtil;
  import org.openhab.io.neeo.internal.ServiceContext;
  import org.openhab.io.neeo.internal.models.NeeoSystemInfo;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import com.google.gson.Gson;
  import com.google.gson.JsonParseException;
  
  /**
   * An implementations of {@link BrainDiscovery} that will discovery brains from the MDNS/Zeroconf/Bonjour service
   * announcements
   *
   * @author Tim Roberts - Initial Contribution
   */
  @NonNullByDefault
  public class MdnsBrainDiscovery extends AbstractBrainDiscovery {
  
      /** The logger */
      private final Logger logger = LoggerFactory.getLogger(MdnsBrainDiscovery.class);
  
      /** The lock that controls access to the {@link #systems} set */
      private final Lock systemsLock = new ReentrantLock();
  
      /** The set of {@link NeeoSystemInfo} that has been discovered */
      private final Map<NeeoSystemInfo, InetAddress> systems = new HashMap<>();
  
      /** The MDNS listener used. */
      private final ServiceListener mdnsListener = new ServiceListener() {
  
          @Override
          public void serviceAdded(@Nullable ServiceEvent event) {
              if (event != null) {
                  considerService(event.getInfo());
              }
          }
  
          @Override
          public void serviceRemoved(@Nullable ServiceEvent event) {
              if (event != null) {
                  removeService(event.getInfo());
              }
          }
  
          @Override
          public void serviceResolved(@Nullable ServiceEvent event) {
              if (event != null) {
                  considerService(event.getInfo());
              }
          }
      };
  
      /** The service context */
      private final ServiceContext context;
  
      /** The scheduler used to schedule tasks */
      private final ScheduledExecutorService scheduler = ThreadPoolManager
              .getScheduledPool(NeeoConstants.THREAD_POOL_NAME);
  
      private final Gson gson = new Gson();
  
      /** The file we store definitions in */
      private final File file = new File(NeeoConstants.FILENAME_DISCOVEREDBRAINS);
  
      private final ClientBuilder clientBuilder;
  
      /**
       * Creates the MDNS brain discovery from the given {@link ServiceContext}
       *
       * @param context the non-null service context
       */
      public MdnsBrainDiscovery(ServiceContext context, ClientBuilder clientBuilder) {
          Objects.requireNonNull(context, "context cannot be null");
          this.context = context;
          this.clientBuilder = clientBuilder;
      }
  
      /**
       * Starts discovery by
       * <ol>
       * <li>Listening to future service announcements from the {@link MDNSClient}</li>
       * <li>Getting a list of all current announcements</li>
       * </ol>
       *
       */
      @Override
      public void startDiscovery() {
          logger.debug("Starting NEEO Brain MDNS Listener");
          context.getMdnsClient().addServiceListener(NeeoConstants.NEEO_MDNS_TYPE, mdnsListener);
  
          scheduler.execute(() -> {
              if (file.exists()) {
                  try {
                      logger.debug("Reading contents of {}", file.getAbsolutePath());
                      final byte[] contents = Files.readAllBytes(file.toPath());
                      final String json = new String(contents, StandardCharsets.UTF_8);
                      final String[] ipAddresses = gson.fromJson(json, String[].class);
                      if (ipAddresses != null) {
                          logger.debug("Restoring discovery from {}: {}", file.getAbsolutePath(),
                                  StringUtils.join(ipAddresses, ','));
                          for (String ipAddress : ipAddresses) {
                              if (StringUtils.isNotBlank(ipAddress)) {
                                  addDiscovered(ipAddress, false);
                              }
                          }
                      }
                  } catch (JsonParseException | UnsupportedOperationException e) {
                      logger.debug("JsonParseException reading {}: {}", file.toPath(), e.getMessage(), e);
                  } catch (IOException e) {
                      logger.debug("IOException reading {}: {}", file.toPath(), e.getMessage(), e);
                  }
              }
  
              for (ServiceInfo info : context.getMdnsClient().list(NeeoConstants.NEEO_MDNS_TYPE)) {
                  considerService(info);
              }
          });
      }
  
      @Override
      public void addListener(DiscoveryListener listener) {
          super.addListener(listener);
          systemsLock.lock();
          try {
              for (Entry<NeeoSystemInfo, InetAddress> entry : systems.entrySet()) {
                  listener.discovered(entry.getKey(), entry.getValue());
              }
          } finally {
              systemsLock.unlock();
          }
      }
  
      /**
       * Return the brain ID and {@link InetAddress} from the {@link ServiceInfo}
       *
       * @param info the non-null {@link ServiceInfo}
       * @return an {@link Entry} that represents the brain ID and the associated IP address
       */
      @Nullable
      private Entry<String, InetAddress> getNeeoBrainInfo(ServiceInfo info) {
          Objects.requireNonNull(info, "info cannot be null");
          if (!StringUtils.equals("neeo", info.getApplication())) {
              logger.debug("A non-neeo application was found for the NEEO MDNS: {}", info);
              return null;
          }
  
          final InetAddress ipAddress = getIpAddress(info);
          if (ipAddress == null) {
              logger.debug("Got a NEEO lookup without an IP address (scheduling a list): {}", info);
              return null;
          }
  
          String model = info.getPropertyString("hon"); // model
          if (model == null) {
              final String server = info.getServer(); // NEEO-xxxxx.local.
              if (server != null) {
                  final int idx = server.indexOf(".");
  